import {LGT} from "./Util.js";
import {UtilApplications} from "./UtilApplications.js";

class PopoutSheet {
	// region External
	static init () {
		Hooks.on("renderSceneConfig", (app, $html, data) => PopoutSheet._doAddButtonSheet(app, $html, data));
		Hooks.on("renderActorSheet", (app, $html, data) => PopoutSheet._doAddButtonSheet(app, $html, data));
		Hooks.on("renderItemSheet", (app, $html, data) => PopoutSheet._doAddButtonSheet(app, $html, data));
		Hooks.on("renderJournalSheet", (app, $html, data) => PopoutSheet._doAddButtonSheet(app, $html, data));
		Hooks.on("renderRollTableConfig", (app, $html, data) => PopoutSheet._doAddButtonSheet(app, $html, data));

		Hooks.on("renderArtBrowserApp", (app, $html, data) => PopoutSheet._doAddButtonSheet(app, $html, data));

		Hooks.on("renderCombatTracker", (app, $html, data) => PopoutSheet._doAddButtonSheet(app, $html, data));
		Hooks.on("renderSceneDirectory", (app, $html, data) => PopoutSheet._doAddButtonSheet(app, $html, data));
		Hooks.on("renderActorDirectory", (app, $html, data) => PopoutSheet._doAddButtonSheet(app, $html, data));
		Hooks.on("renderItemDirectory", (app, $html, data) => PopoutSheet._doAddButtonSheet(app, $html, data));
		Hooks.on("renderJournalDirectory", (app, $html, data) => PopoutSheet._doAddButtonSheet(app, $html, data));
		Hooks.on("renderRollTableDirectory", (app, $html, data) => PopoutSheet._doAddButtonSheet(app, $html, data));
		Hooks.on("renderPlaylistDirectory", (app, $html, data) => PopoutSheet._doAddButtonSheet(app, $html, data));
		Hooks.on("renderCompendiumDirectory", (app, $html, data) => PopoutSheet._doAddButtonSheet(app, $html, data));
		Hooks.on("renderSettings", (app, $html, data) => PopoutSheet._doAddButtonSheet(app, $html, data));
		Hooks.on("renderMacroDirectory", (app, $html, data) => PopoutSheet._doAddButtonSheet(app, $html, data));
	}

	static _doAddButtonSheet (app, $html, data) {
		// N.B.: KaKaRoTo already did this, albeit differently https://github.com/kakaroto/fvtt-module-popout

		const $sheetHeader = app.element.find(`.window-header`);
		$sheetHeader.find(`.pop__btn-open`).remove();

		$(`<a class="pop__btn-open" title="Pop Out (Warning: Experimental)"><span class="fas fa-external-link-alt"></span></a>`)
			.click(evt => this.pHandleButtonClick(evt, app, $html, data))
			.insertBefore($sheetHeader.find(`.close`));
	}

	static pHandleButtonClick (evt, app, $html, data) {
		evt.preventDefault();
		this._handlePopoutClick(app, data);
	}
	// endregion

	static _getDocumentStyleHtml () {
		const out = [];

		const addAsRules = (sheet) => {
			const rules = "cssRules" in sheet ? sheet.cssRules : sheet.rules;
			if (!rules) return;

			const css = [];

			[...(rules || [])].forEach(rule => {
				let str = "cssText" in rule ? rule.cssText : `${rule.selectorText} {\n${rule.style.cssText}\n}\n`;

				// resolve all fonts to absolute paths
				if (str.includes("@font-face")) {
					str = str.replace(/(url\(")([^"]+)("\))/g, (...m) => {
						if (m[2].startsWith("/") || !sheet.href) return `${m[1]}${m[2]}${m[3]}`;
						else {
							const path = (new URL(sheet.href)).pathname.split("/").slice(0, -1).join("/");
							return `${m[1]}${path}/${m[2]}${m[3]}`;
						}
					});
				}
				css.push(str);
			});

			out.push(`<style>
				${css.join("\n")}
			</style>`);
		};

		[...(document.styleSheets || [])].forEach(sheet => {
			try {
				// Attempt to read and modify the styles, to preserve fonts
				addAsRules(sheet);
			} catch (e) {
				console.error(...LGT, e);
				// If we can't read the styles, it's probably a CORS issue--just link the sheet
				if (sheet.href) out.push(`<link rel="stylesheet" href="${sheet.href}">`);
			}
		});

		return out.join("\n");
	}

	static _handlePopoutClick (app, data) {
		const name = app.title || UtilApplications.getDataName(data);

		// Take the classes of the main body in case a game-wide class (such as "dark-mode") has been applied
		const win = open(
			"",
			name,
			`width=800,height=800,location=0,menubar=0,status=0,titlebar=0,toolbar=0,directories=0`,
		);
		win.document.write(`
		<!DOCTYPE html>
		<html lang="en"><head>
			<meta name="viewport" content="width=device-width, initial-scale=1">
			<title>${name}</title>

			${this._getDocumentStyleHtml()}
		</head><body class="flex-col ${document.body.className}"></body></html>
		`);

		const $body = $(win.document.body);

		// Add a flag so we can avoid closing this on ESC press
		app._plut_IsPopout = true;

		// No-op the minimize for when the user e.g. clicks a spell with a template
		const cachedMinimize = app.minimize;
		app.minimize = async () => {};

		app.element.addClass("pop__window");
		$body.append(app.element);

		const $drgResize = app.element.find(`.window-resizable-handle`)
			.addClass("ve-hidden");

		win.addEventListener("unload", () => {
			$(document.body).append(app.element);
			app.element.removeClass("pop__window");
			$drgResize.removeClass("ve-hidden");
			app._plut_IsPopout = false;
			app.minimize = cachedMinimize;
			app.close();
		});
	}
}

export {PopoutSheet};
