const OptionsMenuItemIcon = react.createElement(
	"svg",
	{
		width: 16,
		height: 16,
		viewBox: "0 0 16 16",
		fill: "currentColor",
	},
	react.createElement("path", {
		d: "M13.985 2.383L5.127 12.754 1.388 8.375l-.658.77 4.397 5.149 9.618-11.262z",
	})
);

const OptionsMenuItem = react.memo(({ onSelect, value, isSelected }) => {
	return react.createElement(
		Spicetify.ReactComponent.MenuItem,
		{
			onClick: onSelect,
			icon: isSelected ? OptionsMenuItemIcon : null,
			trailingIcon: isSelected ? OptionsMenuItemIcon : null,
		},
		value
	);
});

const OptionsMenu = react.memo(({ options, onSelect, selected, defaultValue, bold = false }) => {
	/**
	 * <Spicetify.ReactComponent.ContextMenu
	 *      menu = { options.map(a => <OptionsMenuItem>) }
	 * >
	 *      <button>
	 *          <span> {select.value} </span>
	 *          <svg> arrow icon </svg>
	 *      </button>
	 * </Spicetify.ReactComponent.ContextMenu>
	 */
	const menuRef = react.useRef(null);
	return react.createElement(
		Spicetify.ReactComponent.ContextMenu,
		{
			menu: react.createElement(
				Spicetify.ReactComponent.Menu,
				{},
				options.map(({ key, value }) =>
					react.createElement(OptionsMenuItem, {
						value,
						onSelect: () => {
							onSelect(key);
							// Close menu on item click
							menuRef.current?.click();
						},
						isSelected: selected?.key === key,
					})
				)
			),
			trigger: "click",
			action: "toggle",
			renderInline: false,
		},
		react.createElement(
			"button",
			{
				className: "optionsMenu-dropBox",
				ref: menuRef,
			},
			react.createElement(
				"span",
				{
					className: bold ? "main-type-mestoBold" : "main-type-mesto",
				},
				selected?.value || defaultValue
			),
			react.createElement(
				"svg",
				{
					height: "16",
					width: "16",
					fill: "currentColor",
					viewBox: "0 0 16 16",
				},
				react.createElement("path", {
					d: "M3 6l5 5.794L13 6z",
				})
			)
		)
	);
});

function getMusixmatchTranslationPrefix() {
	if (typeof window !== "undefined" && typeof window.__lyricsPlusMusixmatchTranslationPrefix === "string") {
		return window.__lyricsPlusMusixmatchTranslationPrefix;
	}

	return "musixmatchTranslation:";
}

const TranslationMenu = react.memo(({ friendlyLanguage, hasTranslation, musixmatchLanguages, musixmatchSelectedLanguage }) => {
	const musixmatchTranslationPrefix = getMusixmatchTranslationPrefix();

	const [languageMap, setLanguageMap] = react.useState({});

	react.useEffect(() => {
		let cancelled = false;

		if (typeof ProviderMusixmatch !== "undefined" && ProviderMusixmatch && typeof ProviderMusixmatch.getLanguages === "function") {
			(async () => {
				try {
					const languages = await ProviderMusixmatch.getLanguages();
					if (!cancelled) {
						setLanguageMap(languages);
					}
				} catch (error) {
					console.error("Failed to fetch Musixmatch languages:", error);
				}
			})();
		}

		return () => {
			cancelled = true;
		};
	}, []);

	const items = useMemo(() => {
		let sourceOptions = {
			none: "None",
		};

		const translationDisplayOptions = {
			replace: "Replace original",
			below: "Below original",
		};

		const languageOptions = {
			off: "Off",
			"zh-hans": "Chinese (Simplified)",
			"zh-hant": "Chinese (Traditional)",
			ja: "Japanese",
			ko: "Korean",
		};

		let modeOptions = {
			none: "None",
		};

		const musixmatchDisplay = new Intl.DisplayNames(["en"], { type: "language" });
		const availableMusixmatchLanguages = Array.isArray(musixmatchLanguages) ? [...new Set(musixmatchLanguages.filter(Boolean))] : [];
		const activeMusixmatchLanguage = musixmatchSelectedLanguage && musixmatchSelectedLanguage !== "none" ? musixmatchSelectedLanguage : null;
		if (hasTranslation.musixmatch && activeMusixmatchLanguage) {
			availableMusixmatchLanguages.push(activeMusixmatchLanguage);
		}

		if (availableMusixmatchLanguages.length) {
			const musixmatchOptionsArray = availableMusixmatchLanguages.map((code) => {
				let label = "";
				try {
					if (languageMap && languageMap[code]) {
						label = languageMap[code];
					} else {
						label = musixmatchDisplay.of(code) ?? code.toUpperCase();
					}
				} catch (e) {
					label = code.toUpperCase();
				}
				return {
					key: `${musixmatchTranslationPrefix}${code}`,
					label: `${label} (Musixmatch)`,
				};
			});

			musixmatchOptionsArray.sort((a, b) => a.label.localeCompare(b.label));

			const musixmatchOptions = musixmatchOptionsArray.reduce((acc, { key, label }) => {
				acc[key] = label;
				return acc;
			}, {});
			sourceOptions = { ...sourceOptions, ...musixmatchOptions };
		}

		if (hasTranslation.netease) {
			sourceOptions = {
				...sourceOptions,
				neteaseTranslation: "Chinese (Netease)",
			};
		}

		switch (friendlyLanguage) {
			case "japanese": {
				modeOptions = {
					furigana: "Furigana",
					romaji: "Romaji",
					hiragana: "Hiragana",
					katakana: "Katakana",
				};
				break;
			}
			case "korean": {
				modeOptions = {
					romaja: "Romaja",
				};
				break;
			}
			case "chinese": {
				modeOptions = {
					cn: "Simplified Chinese",
					hk: "Traditional Chinese (Hong Kong)",
					tw: "Traditional Chinese (Taiwan)",
				};
				break;
			}
		}

		const configItems = [
			{
				desc: "Translation Provider",
				key: "translate:translated-lyrics-source",
				type: ConfigSelection,
				options: sourceOptions,
				renderInline: true,
			},
			{
				desc: "Translation Display",
				key: "translate:display-mode",
				type: ConfigSelection,
				options: translationDisplayOptions,
				renderInline: true,
			},
			{
				desc: "Language Override",
				key: "translate:detect-language-override",
				type: ConfigSelection,
				options: languageOptions,
				renderInline: true,
				// for songs in languages that support translation but not Convert (e.g., English), the option is disabled.
				when: () => friendlyLanguage,
			},
			{
				desc: "Display Mode",
				key: `translation-mode:${friendlyLanguage}`,
				type: ConfigSelection,
				options: modeOptions,
				renderInline: true,
				// for songs in languages that support translation but not Convert (e.g., English), the option is disabled.
				when: () => friendlyLanguage,
			},
			{
				desc: "Convert",
				key: "translate",
				type: ConfigSlider,
				trigger: "click",
				action: "toggle",
				renderInline: true,
				// for songs in languages that support translation but not Convert (e.g., English), the option is disabled.
				when: () => friendlyLanguage,
			},
		];

		return configItems;
	}, [
		friendlyLanguage,
		hasTranslation.musixmatch,
		hasTranslation.netease,
		Array.isArray(musixmatchLanguages) ? musixmatchLanguages.join(",") : "",
		musixmatchSelectedLanguage || "",
		musixmatchTranslationPrefix,
		languageMap,
	]);

	useEffect(() => {
		// Currently opened Context Menu does not receive prop changes
		// If we were to use keys the Context Menu would close on re-render
		const event = new CustomEvent("lyrics-plus", {
			detail: {
				type: "translation-menu",
				items,
			},
		});
		document.dispatchEvent(event);
	}, [friendlyLanguage, items]);

	return react.createElement(
		Spicetify.ReactComponent.TooltipWrapper,
		{
			label: "Conversion",
		},
		react.createElement(
			"div",
			{
				className: "lyrics-tooltip-wrapper",
			},
			react.createElement(
				Spicetify.ReactComponent.ContextMenu,
				{
					menu: react.createElement(
						Spicetify.ReactComponent.Menu,
						{},
						react.createElement("h3", null, " Conversions"),
						react.createElement(OptionList, {
							type: "translation-menu",
							items,
							onChange: (name, value) => {
								if (name === "translate") {
									CONFIG.visual["translate:translated-lyrics-source"] = "none";
									localStorage.setItem(`${APP_NAME}:visual:translate:translated-lyrics-source`, "none");
								}
								if (name === "translate:translated-lyrics-source") {
									const hasTranslationProvider = typeof value === "string" && value !== "none";
									if (hasTranslationProvider && CONFIG.visual.translate) {
										CONFIG.visual.translate = false;
										localStorage.setItem(`${APP_NAME}:visual:translate`, "false");
									}

									let nextMusixmatchLanguage = "none";
									if (typeof value === "string" && value.startsWith(musixmatchTranslationPrefix)) {
										nextMusixmatchLanguage = value.slice(musixmatchTranslationPrefix.length) || "none";
									}

									if (CONFIG.visual["musixmatch-translation-language"] !== nextMusixmatchLanguage) {
										CONFIG.visual["musixmatch-translation-language"] = nextMusixmatchLanguage;
										localStorage.setItem(`${APP_NAME}:visual:musixmatch-translation-language`, nextMusixmatchLanguage);
									}
								}

								CONFIG.visual[name] = value;
								localStorage.setItem(`${APP_NAME}:visual:${name}`, value);
								lyricContainerUpdate?.();
							},
						})
					),
					trigger: "click",
					action: "toggle",
					renderInline: true,
				},
				react.createElement(
					"button",
					{
						className: "lyrics-config-button",
					},
					react.createElement(
						"p1",
						{
							width: 16,
							height: 16,
							viewBox: "0 0 16 10.3",
							fill: "currentColor",
						},
						"⇄"
					)
				)
			)
		)
	);
});

const AdjustmentsMenu = react.memo(({ mode, hasPerformer }) => {
	return react.createElement(
		Spicetify.ReactComponent.TooltipWrapper,
		{
			label: "Adjustments",
		},
		react.createElement(
			"div",
			{
				className: "lyrics-tooltip-wrapper",
			},
			react.createElement(
				Spicetify.ReactComponent.ContextMenu,
				{
					menu: react.createElement(
						Spicetify.ReactComponent.Menu,
						{},
						react.createElement("h3", null, " Adjustments"),
						react.createElement(OptionList, {
							items: [
								{
									desc: "Font size",
									key: "font-size",
									type: ConfigAdjust,
									min: fontSizeLimit.min,
									max: fontSizeLimit.max,
									step: fontSizeLimit.step,
								},
								{
									desc: "Track delay",
									key: "delay",
									type: ConfigAdjust,
									min: Number.NEGATIVE_INFINITY,
									max: Number.POSITIVE_INFINITY,
									step: 250,
									when: () => mode === SYNCED || mode === KARAOKE,
								},
								{
									desc: "Compact",
									key: "synced-compact",
									type: ConfigSlider,
									when: () => mode === SYNCED || mode === KARAOKE,
								},
								{
									desc: "Show performers",
									key: "show-performers",
									type: ConfigSlider,
									when: () => hasPerformer && (mode === SYNCED || mode === KARAOKE || mode === UNSYNCED),
								},
								{
									desc: "Dual panel",
									key: "dual-genius",
									type: ConfigSlider,
									when: () => mode === GENIUS,
								},
							],
							onChange: (name, value) => {
								CONFIG.visual[name] = value;
								localStorage.setItem(`${APP_NAME}:visual:${name}`, value);
								name === "delay" && localStorage.setItem(`lyrics-delay:${Spicetify.Player.data.item.uri}`, value);
								lyricContainerUpdate?.();
							},
						})
					),
					trigger: "click",
					action: "toggle",
					renderInline: true,
				},
				react.createElement(
					"button",
					{
						className: "lyrics-config-button",
					},
					react.createElement(
						"svg",
						{
							width: 16,
							height: 16,
							viewBox: "0 0 16 10.3",
							fill: "currentColor",
						},
						react.createElement("path", {
							d: "M 10.8125,0 C 9.7756347,0 8.8094481,0.30798341 8,0.836792 7.1905519,0.30798341 6.2243653,0 5.1875,0 2.3439941,0 0,2.3081055 0,5.15625 0,8.0001222 2.3393555,10.3125 5.1875,10.3125 6.2243653,10.3125 7.1905519,10.004517 8,9.4757081 8.8094481,10.004517 9.7756347,10.3125 10.8125,10.3125 13.656006,10.3125 16,8.0043944 16,5.15625 16,2.3123779 13.660644,0 10.8125,0 Z M 8,2.0146484 C 8.2629394,2.2503662 8.4963378,2.5183106 8.6936034,2.8125 H 7.3063966 C 7.5036622,2.5183106 7.7370606,2.2503662 8,2.0146484 Z M 6.619995,4.6875 C 6.6560059,4.3625487 6.7292481,4.0485841 6.8350831,3.75 h 2.3298338 c 0.1059572,0.2985841 0.1790772,0.6125487 0.21521,0.9375 z M 9.380005,5.625 C 9.3439941,5.9499512 9.2707519,6.2639159 9.1649169,6.5625 H 6.8350831 C 6.7291259,6.2639159 6.6560059,5.9499512 6.6198731,5.625 Z M 5.1875,9.375 c -2.3435059,0 -4.25,-1.8925781 -4.25,-4.21875 0,-2.3261719 1.9064941,-4.21875 4.25,-4.21875 0.7366944,0 1.4296875,0.1899414 2.0330809,0.5233154 C 6.2563478,2.3981934 5.65625,3.7083741 5.65625,5.15625 c 0,1.4478759 0.6000978,2.7580566 1.5643309,3.6954347 C 6.6171875,9.1850584 5.9241944,9.375 5.1875,9.375 Z M 8,8.2978516 C 7.7370606,8.0621337 7.5036622,7.7938231 7.3063966,7.4996337 H 8.6936034 C 8.4963378,7.7938231 8.2629394,8.0621338 8,8.2978516 Z M 10.8125,9.375 C 10.075806,9.375 9.3828125,9.1850584 8.7794191,8.8516847 9.7436522,7.9143066 10.34375,6.6041259 10.34375,5.15625 10.34375,3.7083741 9.7436522,2.3981934 8.7794191,1.4608154 9.3828125,1.1274414 10.075806,0.9375 10.8125,0.9375 c 2.343506,0 4.25,1.8925781 4.25,4.21875 0,2.3261719 -1.906494,4.21875 -4.25,4.21875 z m 0,0",
						})
					)
				)
			)
		)
	);
});
