import { world, system, Player, Entity, BlockPermutation, EntityHealthComponent } from "@minecraft/server";
import { getScoreUtility, setScoreUtility, operationScoreUtility, scoreboardList } from "./scoreboard";
import { fillCommandReplaceAir, getDistance, applySelfKnockback, exeFlying, exeStayInAir, ensureEffect, isInputIdle } from "./function";
import { scriptevent } from "./scriptevent";
import { pressedSneak, releasedSneak } from "./sneak";
import { customCompItem } from "./customComp/customComp_item";
import { updateStatus } from "./status";
import { entityDie } from "./entityDie";
import { entityHurt } from "./entityHurt";

world.afterEvents.entityHurt.subscribe(ev =>{
	entityHurt(ev);
});
world.afterEvents.entityDie.subscribe(ev => {
	entityDie(ev);
});
system.beforeEvents.startup.subscribe(ev => {
	customCompItem(ev.itemComponentRegistry);
});
world.afterEvents.worldLoad.subscribe(() => {
	for(const worldDynamicPropId of worldDynamicPropList){
		const worldDynamicProp = world.getDynamicProperty(worldDynamicPropId);
		if(worldDynamicProp==undefined){
			world.setDynamicProperty(worldDynamicPropId,true);
		}
	}
	for(const scoreboardObj of scoreboardList){
		if(world.scoreboard.getObjective(scoreboardObj.id) == null){
			world.scoreboard.addObjective(scoreboardObj.id,"");
		}
	}
});
const worldDynamicPropList = [
	"block_breakable","block_replaceable"
]
world.afterEvents.playerButtonInput.subscribe(ev=>{

	const player = ev.player;
	const input = ev.button;
	const newButtonState = ev.newButtonState;
	if(player.getGameMode()=="spectator") return;
	if(input == "Sneak"){
		if(newButtonState == "Pressed"){
			pressedSneak(player);
		}else{
			releasedSneak(player);
		}
	}
	else{
		if(newButtonState != "Pressed") return;
	}
});
// scriptevent
system.afterEvents.scriptEventReceive.subscribe(ev => {
	scriptevent(ev);
});
// tick
system.runInterval(() => {
	const players = world.getAllPlayers();
	for(const player of players){
		const healthComp = player.getComponent("health");
		const currentHealth = healthComp.currentValue;
		const effectiveMaxHealth = healthComp.effectiveMax;
		showActionbar(player,currentHealth,effectiveMaxHealth);
		if(system.currentTick%20 === 0){
			nenEffect(player);
			naturalRegeneration(player,healthComp,currentHealth);
		}
		else if(system.currentTick%3 === 0){
			nenScores(player);
			updateStatus(player);
		}
	}
});
/**
 * @param {Player} player 
 * @param {EntityHealthComponent} healthComp 
 * @param {Number} currentHealth 
 */
function naturalRegeneration(player,healthComp,currentHealth){
	const hungerComp = player.getComponent("player.hunger");
	if(hungerComp.currentValue!=20) return;
	const defaultHealth = healthComp.defaultValue;
	if(currentHealth>=defaultHealth) return;
	const saturationComp = player.getComponent("player.saturation");
	const satuValue = saturationComp.currentValue;
	if(satuValue>=1){
		saturationComp.setCurrentValue(satuValue-1);
	}
	else{
		hungerComp.setCurrentValue(Math.max(0,hungerComp.currentValue-1));
	}
	healthComp.setCurrentValue(currentHealth+1);
}
/**
 * @param {Player} player 
 */
function nenEffect(player){
	const isTen = player.matches({families:["ten"]});
	const isRen = player.matches({families:["ren"]});
	const isGyo = player.matches({families:["gyo"]});
	const isEn = player.matches({families:["en"]});
	const isShu = player.matches({families:["shu"]});
	const isKo = player.matches({families:["ko"]});
	const isKen = player.matches({families:["ken"]});
	const isRyu = player.matches({families:["ryu"]});
	const form = player.getProperty("hxc:form");
	const ryuType = player.getProperty("hxc:ryu");
	const Level = player.getProperty("hxc:level");
	// Ten
	if(isTen){
		const resAmp = Level < 20 ? 0 : 1;
		player.addEffect("resistance",30,{amplifier:resAmp,showParticles:false});
		if(Level >= 20){
			player.addEffect("strength",30,{amplifier:0,showParticles:false});
		}
	}
	// Ren
	else if(isRen){
		const strAmp = Level < 20 ? 0 : 1;
		player.addEffect("strength",30,{amplifier:strAmp,showParticles:false});
		if(Level >= 20){
			player.addEffect("resistance",30,{amplifier:0,showParticles:false});
		}
	}
	// Gyo
	else if(isGyo){
		player.addEffect("night_vision",50,{amplifier:0,showParticles:false});
	}
	// En
	else if(isEn){
		player.addEffect("night_vision",50,{amplifier:0,showParticles:false});
		player.addEffect("resistance",30,{amplifier:1,showParticles:false});
		if(Level >= 40){
			player.addEffect("strength",30,{amplifier:1,showParticles:false});
		}
	}
	// Shu
	else if(isShu){
		player.addEffect("strength",30,{amplifier:1,showParticles:false});
		player.addEffect("resistance",30,{amplifier:0,showParticles:false});
	}
	// Ko
	else if(isKo){
		const strAmp = Level < 50 ? 2 : 3;
		player.addEffect("strength",30,{amplifier:strAmp,showParticles:false});
		if(Level >= 40){
			player.addEffect("resistance",30,{amplifier:0,showParticles:false});
		}
	}
	// Ken
	else if(isKen){
		const strAmp = Level < 50 ? 1 : Level < 80 ? 2 : 3;
		const resAmp = Level < 50 ? 1 : Level < 80 ? 2 : 3;
		player.addEffect("strength",30,{amplifier:strAmp,showParticles:false});
		player.addEffect("resistance",30,{amplifier:2,showParticles:false});
	}
	// Ryu
	else if(isRyu){
		if(ryuType==0){
			const strAmp = Level < 80 ? 1 : 2;
			const resAmp = Level < 80 ? 2 : 3;
			player.addEffect("strength",30,{amplifier:strAmp,showParticles:false});
			player.addEffect("speed",30,{amplifier:0,showParticles:false});
			player.addEffect("resistance",30,{amplifier:resAmp,showParticles:false});
		}
		else if(ryuType==1){
			const strAmp = Level < 80 ? 2 : 3;
			const resAmp = Level < 80 ? 1 : 2;
			player.addEffect("strength",30,{amplifier:strAmp,showParticles:false});
			player.addEffect("speed",30,{amplifier:0,showParticles:false});
			player.addEffect("resistance",30,{amplifier:resAmp,showParticles:false});
		}
		else if(ryuType==2){
			const strAmp = Level < 80 ? 1 : 2;
			const resAmp = Level < 80 ? 1 : 2;
			player.addEffect("strength",30,{amplifier:strAmp,showParticles:false});
			player.addEffect("speed",30,{amplifier:1,showParticles:false});
			player.addEffect("resistance",30,{amplifier:resAmp,showParticles:false});
		}
		else if(ryuType==3){
			const strAmp = Level < 80 ? 2 : 3;
			const resAmp = Level < 80 ? 1 : 2;
			player.addEffect("strength",30,{amplifier:strAmp,showParticles:false});
			player.addEffect("speed",30,{amplifier:1,showParticles:false});
			player.addEffect("resistance",30,{amplifier:resAmp,showParticles:false});
		}
		else if(ryuType==4){
			const strAmp = Level < 80 ? 2 : 3;
			const resAmp = Level < 80 ? 2 : 3;
			player.addEffect("strength",30,{amplifier:strAmp,showParticles:false});
			player.addEffect("speed",30,{amplifier:0,showParticles:false});
			player.addEffect("resistance",30,{amplifier:resAmp,showParticles:false});
		}
		else if(ryuType==5){
			const strAmp = Level < 80 ? 1 : 2;
			const resAmp = Level < 80 ? 2 : 3;
			player.addEffect("strength",30,{amplifier:strAmp,showParticles:false});
			player.addEffect("speed",30,{amplifier:1,showParticles:false});
			player.addEffect("resistance",30,{amplifier:resAmp,showParticles:false});
		}
	}
	// Form
	if(form=="gon_adult"){
		if(Level >= 50 && Level < 60){
			player.addEffect("strength",30,{amplifier:2,showParticles:false});
			player.addEffect("resistance",30,{amplifier:2,showParticles:false});
		}
		else if(Level >= 60 && Level < 70){
			player.addEffect("strength",30,{amplifier:3,showParticles:false});
			player.addEffect("resistance",30,{amplifier:2,showParticles:false});
			player.addEffect("speed",30,{amplifier:0,showParticles:false});
		}
		else if(Level >= 70 && Level < 80){
			player.addEffect("strength",30,{amplifier:4,showParticles:false});
			player.addEffect("resistance",30,{amplifier:3,showParticles:false});
			player.addEffect("speed",30,{amplifier:0,showParticles:false});
		}
		else if(Level >= 80 && Level < 100){
			player.addEffect("strength",30,{amplifier:5,showParticles:false});
			player.addEffect("resistance",30,{amplifier:3,showParticles:false});
			player.addEffect("speed",30,{amplifier:1,showParticles:false});
		}
		else if(Level >= 100 && Level < 150){
			player.addEffect("strength",30,{amplifier:6,showParticles:false});
			player.addEffect("resistance",30,{amplifier:3,showParticles:false});
			player.addEffect("speed",30,{amplifier:1,showParticles:false});
		}
		else if(Level >= 150){
			player.addEffect("strength",30,{amplifier:7,showParticles:false});
			player.addEffect("resistance",30,{amplifier:3,showParticles:false});
			player.addEffect("speed",30,{amplifier:1,showParticles:false});
		}
	}
	else if(form=="killua_godspeed"){
		const strAmp = Level < 75 ? 4 : 5;
		const resAmp = Level < 60 ? 2 : 3;
		player.addEffect("strength",30,{amplifier:strAmp,showParticles:false});
		player.addEffect("resistance",30,{amplifier:resAmp,showParticles:false});
		player.addEffect("speed",30,{amplifier:2,showParticles:false});
	}
	else if(form=="meruem_release"){
		const strAmp = Level < 85 ? 5 : 6;
		player.addEffect("strength",30,{amplifier:strAmp,showParticles:false});
		player.addEffect("resistance",30,{amplifier:3,showParticles:false});
		player.addEffect("speed",30,{amplifier:2,showParticles:false});
	}
	else if(form=="feitan_angry"){
		const strAmp = Level < 75 ? 3 : 4;
		player.addEffect("strength",30,{amplifier:3,showParticles:false});
		player.addEffect("resistance",30,{amplifier:3,showParticles:false});
		player.addEffect("fire_resistance",30,{amplifier:0,showParticles:false});
		player.addEffect("speed",30,{amplifier:1,showParticles:false});
	}
}
/**
 * @param {Player} player 
 */
function nenScores(player){
	const isTen = player.matches({families:["ten"]});
	const isRen = player.matches({families:["ren"]});
	const isGyo = player.matches({families:["gyo"]});
	const isEn = player.matches({families:["en"]});
	const isShu = player.matches({families:["shu"]});
	const isKo = player.matches({families:["ko"]});
	const isKen = player.matches({families:["ken"]});
	const isRyu = player.matches({families:["ryu"]});
	const form = player.getProperty("hxc:form");
	// Ten
	if(isTen){
		player.runCommand("scoreboard players remove @s nen 8");
		player.runCommand("event entity @s[scores={nen=..0}] no_nen");
		player.dimension.spawnParticle("hxc:nen_aura1",player.location);
	}
	// Ren
	else if(isRen){
		player.runCommand("scoreboard players remove @s nen 9");
		player.runCommand("event entity @s[scores={nen=..0}] no_nen");
		player.dimension.spawnParticle("hxc:nen_aura1",player.location);
	}
	// Gyo
	else if(isGyo){
		player.runCommand("scoreboard players remove @s nen 8");
		player.runCommand("event entity @s[scores={nen=..0}] no_nen");
		player.dimension.spawnParticle("hxc:gyo_particle",player.location);
	}
	// En
	else if(isEn){
		player.runCommand("scoreboard players remove @s nen 9");
		player.runCommand("event entity @s[scores={nen=..0}] no_nen");
		player.dimension.spawnParticle("hxc:en_particle1",player.location);
	}
	// Shu
	else if(isShu){
		player.runCommand("scoreboard players remove @s nen 8");
		player.runCommand("event entity @s[scores={nen=..0}] no_nen");
	}
	// Ko
	else if(isKo){
		player.runCommand("scoreboard players remove @s nen 8");
		player.runCommand("event entity @s[scores={nen=..0}] no_nen");
	}
	// Ken
	else if(isKen){
		player.runCommand("scoreboard players remove @s nen 10");
		player.runCommand("event entity @s[scores={nen=..0}] no_nen");
		player.dimension.spawnParticle("hxc:nen_aura1",player.location);
	}
	// Ryu
	else if(isRyu){
		player.runCommand("scoreboard players remove @s nen 10");
		player.runCommand("event entity @s[scores={nen=..0}] no_nen");
		player.dimension.spawnParticle("hxc:nen_aura1",player.location);
	}
	// Form
	if(form=="gon_adult"){
		player.runCommand("scoreboard players remove @s nen 8");
		player.runCommand("execute as @s[scores={nen=..1}] run scriptevent hxc:skill_gon_adult_end");
		player.dimension.spawnParticle("hxc:nen_aura5",player.location);
	}
	else if(form=="killua_godspeed"){
		player.runCommand("scoreboard players remove @s nen 9");
		player.runCommand("execute as @s[scores={nen=..1}] run scriptevent hxc:skill_killua_godspeed_end");
		player.dimension.spawnParticle("hxc:killua_godspeed_particle",player.location);
		player.dimension.spawnParticle("hxc:nen_godspeed_particle",player.location);
	}
	else if(form=="meruem_release"){
		player.runCommand("scoreboard players remove @s nen 9");
		player.runCommand("execute as @s[scores={nen=..1}] run scriptevent hxc:skill_release_end");
		player.dimension.spawnParticle("hxc:meruem_nen_aura",player.location);
		player.dimension.spawnParticle("hxc:nen_aura2",player.location);
	}
	else if(form=="feitan_angry"){
		player.runCommand("scoreboard players remove @s nen 9");
		player.runCommand("execute as @s[scores={nen=..1}] run scriptevent hxc:skill_feitan_angry_end");
		player.dimension.spawnParticle("hxc:feitan_angry_nen",player.location);
	}
}
/**
 * @param {Number} pctValue
 */
function pct5(pctValue){
	if(pctValue != undefined && pctValue<1){
		const pctRoundValue = Math.round(pctValue*100);
		const tens = Math.floor(pctRoundValue/10);
		const ones = pctRoundValue%10;
		const ones0or5 = tens == 0 ? (ones == 0 ? 0 : 5) : (ones < 5 ? 0 : 5);
		return tens*10 + ones0or5;
	}else{
		return 100;
	}
}
/**
 * @param {Player} player
 */
function actionbarIcon(player){
	const healthComp = player.getComponent("health");
	const currentHealth = healthComp.currentValue;
	const defaultHealth = healthComp.defaultValue;
	const Exp = player.getProperty("hxc:exp");
	const Level = player.getProperty("hxc:level");
	const MAX_EXP = ((Level * 5) + 20) + (Level * 10);
	const nenTxt = `\ue18F  ${getScoreUtility(player,"nen")}/${getScoreUtility(player,"nen_max")}`;
	const guardTxt = player.getProperty("hxc:perfect_guard") ? `  \ue181  §e${getScoreUtility(player,"guard_time")-100}§f  ` : `  \ue181  ${getScoreUtility(player,"guard_time")}  `;
	const healthTxt = `\ue155${Math.ceil(currentHealth)}/${defaultHealth}`;
	const LevelTxt = `\n\ue183   §bLevel: ${Level}`;
	const ExpTxt = `  §bExp: ${Math.ceil(Exp)}/${MAX_EXP}§f`;
	const painPackerTxt = player.getProperty("hxc:hatsu") == 5 ? `  \ue185  ${getScoreUtility(player,"pain_score")} ` : ` `;
	return `§r${nenTxt}${guardTxt}${healthTxt}${LevelTxt}${ExpTxt}${painPackerTxt}`;
}
/**
 * @param {Player} player 
 * @param {Number} currentHealth 
 * @param {Number} effectiveMaxHealth 
 */
function showActionbar(player,currentHealth,effectiveMaxHealth){
	player.onScreenDisplay.setActionBar(
		{
			rawtext:[
				{
					text:
					actionbarIcon(player)
				}
			]
		}
	);
}