import {ImportListCreature} from "./ImportListCreature.js";
import {MixinUserChooseImporter} from "./ImportList.js";
import {UtilGameSettings} from "./UtilGameSettings.js";

class ActorPolymorpher {
	// region External
	static init () {
		if (game.user.isGM) this._init_gm();
		else this._init_player();
	}

	static _isActorTransformed (actor) {
		if (MiscUtil.get(actor.data.flags, "dnd5e", "originalActor")) return true;
		if (MiscUtil.get(actor.data.flags, "dnd5e", "transformOptions")) return true;
		return false;
	}

	static _init_player () {
		// When a player clicks the "restore transformation" button, whisper a prompt to the GM(s)
		$(document.body).on("click", `.restore-transformation`, evt => {
			const actorId = $(evt.currentTarget).closest(`.sheet.actor`).attr("id").replace("actor-", "");
			const actor = CONFIG.Actor.collection.instance.get(actorId);

			if (!this._isActorTransformed(actor)) {
				const msg = `This actor does not appear to be transformed\u2014this may be a bug!`;
				console.warn(msg);
				ui.notfications.warn(msg);
			}

			ChatMessage.create({
				sound: "sounds/notify.wav",
				content: `<p>${game.user.name} has transformed back into their original form, and requests you delete their temporary polymorphed actor "${actor.name.escapeQuotes()}." Proceed?</p><div><button data-plut-actor-delete="${actorId}">Delete</button></div>`,
				user: game.userId,
				type: 4,
				whisper: game.users.contents.filter(it => it.isGM).map(it => it.id),
			});
		});
	}

	static _init_gm () {
		$(document.body).on("click", `[data-plut-actor-delete]`, async evt => {
			const actorId = $(evt.currentTarget).attr("data-plut-actor-delete");
			const actor = CONFIG.Actor.collection.instance.get(actorId);
			if (!actor) return ui.notifications.warn(`Actor "${actorId}" not found!`);

			if (!this._isActorTransformed(actor)) {
				const isDeleteAnyway = await InputUiUtil.pGetUserBoolean({title: "Are You Sure?", htmlDescription: `This actor does not appear to be transformed. Are you sure you want to delete this actor, which may be an original actor?`});
				if (!isDeleteAnyway) return;
			}

			await actor.delete();
			ui.notifications.info(`Deleted actor "${actor.name}"`);
		});
	}

	static async pHandleButtonClick (evt, app, $html, data) {
		if (!game.user.isGM) {
			const messages = [
				game.user.can("ACTOR_CREATE") ? "" : "you lack actor creation permissions",
				game.user.can("ITEM_CREATE") ? "" : "you lack item creation permissions",
				UtilGameSettings.getSafe("dnd5e", "allowPolymorphing") ? "" : "system-wide player polymorphing is disabled",
			].filter(Boolean);

			if (messages.length) return ui.notifications.warn(`Cannot polymorph: ${messages.join("; ")}`);
		}

		const sourceActor = await ActorPolymorpher.ImportList.pGetUserChoice(
			{
				id: "creatures-actorPolymorpher",
				name: "Creatures",
				singleName: "Creature",

				wizardTitleWindow: "Select Source",
				wizardTitlePanel3: "Configure and Open List",
				wizardTitleButtonOpenImporter: "Open List",
			},
			"actorPolymorpher",
		);
		if (sourceActor == null) return;
		await this._doFakeActorDrop(app.actor, sourceActor);
	}

	// endregion

	// region Based on `Actor5e._onDropActor`
	static async _doFakeActorDrop (actor, sourceActor) {
		// Define a function to record polymorph settings for future use
		const rememberOptions = html => {
			const options = {};
			html.find("input").each((i, el) => {
				options[el.name] = el.checked;
			});
			const settings = mergeObject(UtilGameSettings.getSafe("dnd5e", "polymorphSettings") || {}, options);
			game.settings.set("dnd5e", "polymorphSettings", settings);
			return settings;
		};

		// Create and render the Dialog
		return new Dialog({
			title: game.i18n.localize("DND5E.PolymorphPromptTitle"),
			content: {
				options: UtilGameSettings.getSafe("dnd5e", "polymorphSettings"),
				i18n: CONFIG.DND5E.polymorphSettings,
				isToken: actor.isToken,
			},
			default: "accept",
			buttons: {
				accept: {
					icon: `<i class="fas fa-check"></i>`,
					label: game.i18n.localize("DND5E.PolymorphAcceptSettings"),
					callback: html => actor.transformInto(sourceActor, rememberOptions(html)),
				},
				wildshape: {
					icon: `<i class="fas fa-paw"></i>`,
					label: game.i18n.localize("DND5E.PolymorphWildShape"),
					callback: html => actor.transformInto(sourceActor, {
						keepBio: true,
						keepClass: true,
						keepMental: true,
						mergeSaves: true,
						mergeSkills: true,
						transformTokens: rememberOptions(html).transformTokens,
					}),
				},
				polymorph: {
					icon: `<i class="fas fa-pastafarianism"></i>`,
					label: game.i18n.localize("DND5E.Polymorph"),
					callback: html => actor.transformInto(sourceActor, {
						transformTokens: rememberOptions(html).transformTokens,
					}),
				},
				cancel: {
					icon: `<i class="fas fa-times"></i>`,
					label: game.i18n.localize("Cancel"),
				},
			},
		}, {
			classes: ["dialog", "dnd5e"],
			width: 600,
			template: "systems/dnd5e/templates/apps/polymorph-prompt.html",
		}).render(true);
	}
	// endregion
}

ActorPolymorpher.ImportList = class extends MiscUtil.mix(ImportListCreature).with(MixinUserChooseImporter) {
	constructor (externalData) {
		super(
			externalData,
			{
				title: "Select Creature",
			},
			{
				titleButtonRun: "Select",
			},
		);
	}

	getData () {
		const out = super.getData();
		out.buttonsAdditional = [
			{
				name: "btn-run-mods",
				text: "Select with CR Scaling/Rename",
			},
		];
		return out;
	}
};

export {ActorPolymorpher};
