import Logger from "./utils/Logger";
import M5CharacterSheet from "./module/sheets/M5CharacterSheet";
import preloadTemplates from "./PreloadTemplates";
import { M5Character } from "./module/actors/M5Character";
import { M5Skill } from "./module/M5Base";
import { M5ItemSheet } from "./module/sheets/M5ItemSheet";
import { M5Item } from "./module/items/M5Item";

Hooks.once("init", async () => {
	Logger.log("M5 | Initialisierung Midgard 5");

	Handlebars.registerHelper("times", (n: number, block) => {
		var accum = "";
		for (let i = 0; i < n; ++i) accum += block.fn(i);
		return accum;
	});

	Handlebars.registerHelper("array", (arr: any[], index: number) => {
		return arr[index];
	});

	Handlebars.registerHelper("m5concat", (...values) => {
		const options = values.pop();
		const join = options.hash?.join || "";
		//return new Handlebars.SafeString(values.join(join));
		return values.map((val) => val.toString()).join(join);
	});

	Handlebars.registerHelper("add", (...values) => {
		const options = values.pop();
		return values.reduce((prev, cur) => prev + cur);
	});

	Handlebars.registerHelper("localizeMidgard", (str: string) => {
		const template = Handlebars.compile("{{localize value}}");
		return template({
			value: "midgard5." + str,
		});
	});

	Handlebars.registerHelper("skillBonus", (actorId: string, skill: M5Skill) => {
		const actor = (game as Game).actors.get(actorId) as M5Character;
		return actor.skillBonus(skill).toString();
	});

	Handlebars.registerHelper("skillEw", (actorId: string, skill: M5Skill) => {
		const actor = (game as Game).actors.get(actorId) as M5Character;
		return actor.skillEw(skill).toString();
	});

	Handlebars.registerHelper("skill", (skillId: string) => {
		return (game as Game).items.get(skillId);
	});

	Handlebars.registerHelper("itemValue", (id: string, path: string) => {
		let obj = (game as Game).items.get(id);
		path.split(".").forEach((p) => (obj = obj[p]));
		return `${obj}`;
	});

	Handlebars.registerHelper("actorItemValue", (actorId: any, itemId: string, path: string) => {
		//console.log("actorItemValue", actorId, itemId, path)
		const actor = (game as Game).actors.get(actorId);
		let obj = actor.items.get(itemId).system;
		path.split(".").forEach((p) => {
			if (obj) obj = obj[p];
		});
		return `${obj}`;
	});

	Handlebars.registerHelper("icon", (relpath: string) => {
		return `systems/midgard5/assets/icons/${relpath}`;
	});

	Handlebars.registerHelper("isSkillInList", (skillName: string, list: any) => {
		for (let key in list) {
			if (list[key]?.label?.toLowerCase() === skillName?.toLowerCase()) {
				return true;
			}
		}
		return false;
	});

	Handlebars.registerHelper("stripHtml", function (param) {
		var regex = /(<([^>]+)>)/gi;
		return param.replace(regex, "");
	});

	Handlebars.registerHelper("contains", (label: string, contains: string) => {
		return label.toLowerCase().includes(contains.toLowerCase());
	});

	// Default Sheet für Items definieren und das Standardsheet deaktivieren
	Items.unregisterSheet("core", ItemSheet);
	Items.registerSheet("midgard5", M5ItemSheet, { makeDefault: true });

	// Default Sheet für Actors definieren und das Standardsheet deaktivieren
	Actors.unregisterSheet("core", ActorSheet);
	Actors.registerSheet("midgard5", M5CharacterSheet, { makeDefault: true });

	CONFIG.Actor.documentClass = M5Character;
	CONFIG.Item.documentClass = M5Item;
	//RegisterSettings();
	await preloadTemplates();
});

Hooks.once("setup", () => {
	Logger.log("Template module is being setup.");
});

Hooks.on("getChatLogEntryContext", function (html, options) {
	options.push(
		{
			name: "LP & AP Schaden",
			icon: '<i class="fas fa-tint"></i>',
			condition: (li) => {
				// Only show this context menu if there are re-rollable dice in the message
				const damageRolls = li.find(".apply-damage").length;
				console.log(game["user"].isGm);

				// All must be true to show the reroll dialogue
				// The button doesn't work for the GM right now, so we don't need to show it
				return game["user"].character && damageRolls > 0;
			},
			callback: (li) => applyDamage(li, 2),
		},
		{
			name: "AP Schaden",
			icon: '<i class="fas fa-shield-alt"></i>',
			condition: (li) => {
				// Only show this context menu if there are re-rollable dice in the message
				const damageRolls = li.find(".apply-damage").length;

				// All must be true to show the reroll dialogue
				// The button doesn't work for the GM right now, so we don't need to show it
				return game["user"].character && damageRolls > 0;
			},
			callback: (li) => applyDamage(li, 1),
		},
		{
			name: "LP & AP Heilen",
			icon: '<i class="fas fa-heart"></i>',
			condition: (li) => {
				// Only show this context menu if there are re-rollable dice in the message
				const damageRolls = li.find(".apply-damage").length;

				// All must be true to show the reroll dialogue
				// The button doesn't work for the GM right now, so we don't need to show it
				return game["user"].character && damageRolls > 0;
			},
			callback: (li) => applyDamage(li, -1),
		},
		{
			name: "AP Heilen",
			icon: '<i class="far fa-heart"></i>',
			condition: (li) => {
				// Only show this context menu if there are re-rollable dice in the message
				const damageRolls = li.find(".apply-damage").length;

				// All must be true to show the reroll dialogue
				// The button doesn't work for the GM right now, so we don't need to show it
				return game["user"].character && damageRolls > 0;
			},
			callback: (li) => applyDamage(li, -2),
		}
	);
});

Hooks.once("ready", () => {
	Logger.ok("Template module is now ready.");
});

async function applyDamage(roll, direction) {
	const damageValue = Array.from(roll.find(".apply-damage") as HTMLElement[])
		.map((x) => Math.max(0, Number(x.innerText)))
		.reduce((prev, curr) => prev + curr, 0);
	const userId = game["user"].character.id;
	const viewedSceneId = game["user"].viewedScene;
	const token = game["actors"].get(userId).getDependentTokens(viewedSceneId)[0]?.delta.syntheticActor;
	const actor = game["user"].character;

	if (token) {
		switch (direction) {
			case 2:
				token["system"].lp.value -= Math.max(0, damageValue - token["system"].calc.stats.lpProtection.value);
			case 1:
				token["system"].ap.value -= Math.max(0, damageValue - token["system"].calc.stats.apProtection.value);
				break;
			case -1:
				token["system"].lp.value += Math.min(damageValue, token["system"].lp.max - damageValue);
			case -2:
				token["system"].ap.value += Math.min(damageValue, token["system"].ap.max - damageValue);
		}
		token.render();
	} else {
		switch (direction) {
			case 2:
				actor["system"].lp.value -= Math.max(0, damageValue - actor["system"].calc.stats.lpProtection.value);
			case 1:
				actor["system"].ap.value -= Math.max(0, damageValue - actor["system"].calc.stats.apProtection.value);
				break;
			case -1:
				actor["system"].lp.value += Math.min(damageValue, actor["system"].lp.max - damageValue);
			case -2:
				actor["system"].ap.value += Math.min(damageValue, actor["system"].ap.max - damageValue);
		}
		actor.render();
	}
}
