import config from "config"
import store from "store"
import { ConfigProvider } from "antd"

export class ThemeController {
	constructor(params) {
		this.params = { ...params }

		this.themeManifestStorageKey = "theme"
		this.modificationStorageKey = "themeModifications"
		this.variantStorageKey = "themeVariation"

		this.theme = null

		this.mutation = null
		this.currentVariant = null

		this.init()

		return this
	}

	static get currentVariant() {
		return document.documentElement.style.getPropertyValue("--themeVariant")
	}

	init = () => {
		let theme = this.getStoragedTheme()
		const modifications = this.getStoragedModifications()
		const variantKey = this.getStoragedVariant()

		if (!theme) {
			// load default theme
			theme = this.getDefaultTheme()
		} else {
			// load URL and initialize theme
		}

		// set global theme
		this.theme = theme

		// override with static vars
		if (theme.staticVars) {
			this.update(theme.staticVars)
		}

		// override theme with modifications
		if (modifications) {
			this.update(modifications)
		}

		// apply variation
		this.applyVariant(variantKey)
	}

	getRootVariables = () => {
		let attributes = document.documentElement.getAttribute("style").trim().split(";")
		attributes = attributes.slice(0, (attributes.length - 1))
		attributes = attributes.map((variable) => {
			let [key, value] = variable.split(":")
			key = key.split("--")[1]

			return [key, value]
		})

		return Object.fromEntries(attributes)
	}

	getDefaultTheme = () => {
		// TODO: Use evite CONSTANTS_API
		return config.defaultTheme
	}

	getStoragedTheme = () => {
		return store.get(this.themeManifestStorageKey)
	}

	getStoragedModifications = () => {
		return store.get(this.modificationStorageKey)
	}

	getStoragedVariant = () => {
		return store.get(this.variantStorageKey)
	}

	setVariant = (variationKey) => {
		return store.set(this.variantStorageKey, variationKey)
	}

	setModifications = (modifications) => {
		return store.set(this.modificationStorageKey, modifications)
	}

	resetDefault = () => {
		store.remove(this.themeManifestStorageKey)
		store.remove(this.modificationStorageKey)

		window.app.settings.set("primaryColor", this.theme.staticVars.primaryColor)

		return this.init()
	}

	update = (update) => {
		if (typeof update !== "object") {
			return false
		}

		this.mutation = {
			...this.theme.staticVars,
			...this.mutation,
			...update
		}

		Object.keys(this.mutation).forEach(key => {
			document.documentElement.style.setProperty(`--${key}`, this.mutation[key])
		})

		document.documentElement.className = `theme-${this.currentVariant}`
		document.documentElement.style.setProperty(`--themeVariant`, this.currentVariant)

		ConfigProvider.config({ theme: this.mutation })
	}

	applyVariant = (variant = (this.theme.defaultVariant ?? "light")) => {
		const values = this.theme.variants[variant]

		if (values) {
			this.currentVariant = variant
			this.update(values)
			this.setVariant(variant)
		}
	}
}

export const extension = {
	key: "theme",
	expose: [
		{
			initialization: [
				async (app, main) => {
					app.ThemeController = new ThemeController()

					main.eventBus.on("darkMode", (value) => {
						if (value) {
							app.ThemeController.applyVariant("dark")
						} else {
							app.ThemeController.applyVariant("light")
						}
					})
					main.eventBus.on("modifyTheme", (value) => {
						app.ThemeController.update(value)
						app.ThemeController.setModifications(app.ThemeController.mutation)
					})
					main.eventBus.on("resetTheme", () => {
						app.ThemeController.resetDefault()
					})

					main.setToWindowContext("ThemeController", app.ThemeController)
				},
			],
		},
	],
}

export default extension