<script lang="ts">
	import { Tab, TabContent } from '$lib/components/common'
	import { sendUserToast } from '$lib/toast'
	import { getContext } from 'svelte'
	import type { AppViewerContext, ComponentCssProperty } from '../../types'
	import { ccomponents, components } from '../component'
	import CssProperty from '../componentsPanel/CssProperty.svelte'
	import { quickStyleProperties } from '../componentsPanel/quickStyleProperties'
	import Tabs from '$lib/components/common/tabs/Tabs.svelte'
	import ConfirmationModal from '$lib/components/common/confirmationModal/ConfirmationModal.svelte'
	import Badge from '$lib/components/common/badge/Badge.svelte'
	import Button from '$lib/components/common/button/Button.svelte'
	import { enterpriseLicense } from '$lib/stores'
	import Tooltip from '$lib/components/Tooltip.svelte'
	import { customisationByComponent, hasStyleValue } from '../componentsPanel/cssUtils'
	import CssMigrationModal from './CSSMigrationModal.svelte'
	import CssPropertyWrapper from './CssPropertyWrapper.svelte'
	import { onMount } from 'svelte'
	import { findComponentSettings } from '../appUtils'

	const { app, cssEditorOpen, selectedComponent } = getContext<AppViewerContext>('AppViewerContext')

	$: component = findComponentSettings($app, $selectedComponent?.[0])?.item?.data

	let tab: 'local' | 'global' = 'local'
	let overrideGlobalCSS: (() => void) | undefined = undefined
	let overrideLocalCSS: (() => void) | undefined = undefined
	$: type = component?.type
	let migrationModal: CssMigrationModal | undefined = undefined

	$: customCssByComponentType =
		component?.type && $app.css
			? Object.entries($app.css[component.type] || {}).map(([id, v]) => ({
					id,
					forceStyle: v?.style != undefined,
					forceClass: v?.['class'] != undefined
			  }))
			: undefined

	function copyLocalToGlobal(name: string, value: ComponentCssProperty | undefined) {
		if (!value) {
			sendUserToast('No local CSS to copy')
		} else {
			const type = component?.type

			if (!type) return

			if (hasStyleValue($app.css?.[type]?.[name])) {
				overrideGlobalCSS = () => {
					$app.css![type]![name] = JSON.parse(JSON.stringify(value))
					app.set($app)
				}
			} else {
				if (!$app.css![type]) {
					initGlobalCss()
				}

				$app.css![type]![name] = JSON.parse(JSON.stringify(value))
				app.set($app)
				sendUserToast('Global CSS copied')
			}
		}
	}

	function copyGlobalToLocal(id: string, value: any) {
		if (!value) {
			sendUserToast('No global CSS to copy')
		} else {
			if (hasStyleValue(value)) {
				overrideLocalCSS = () => {
					component!.customCss![id] = JSON.parse(JSON.stringify(value))
					app.set($app)
				}
			} else {
				component!.customCss![id] = JSON.parse(JSON.stringify(value))
				app.set($app)
				sendUserToast('Local CSS copied')
			}
		}
	}

	function initGlobalCss() {
		// If the global css is not initialised, we initialise it.
		// Should only happen once per app
		if (!$app.css) {
			$app.css = {}
		}

		// If the global css for this component type is not initialised, we initialise it.
		// Should only happen once per component type
		if (
			$app.css &&
			component &&
			!$app.css[component.type]?.style &&
			components[component.type] &&
			$app.css[component.type] === undefined
		) {
			$app.css[component.type] = JSON.parse(JSON.stringify(components[component.type].customCss))
			app.set($app)
		}
	}

	function getSelector(key: string) {
		return customisationByComponent
			.find((c) => c.components.includes(component?.type ?? ''))
			?.selectors.find((s) => {
				return s.customCssKey === key
			})?.selector
	}

	onMount(() => {
		initGlobalCss()
	})
</script>

{#if component}
	{#key component?.id}
		<div class="px-2 flex items-center gap-2 flex-row justify-between">
			{#if !cssEditorOpen}
				<Button
					color="blue"
					size="xs2"
					variant="border"
					on:click={() => {
						$cssEditorOpen = true
					}}
				>
					<div class="flex flex-row gap-1 text-xs items-center">
						Open CSS editor{$enterpriseLicense === undefined ? '  (EE only)' : ''}
						<Tooltip light>
							You can also use the App CSS Editor to customise the CSS of all components.
						</Tooltip>
					</div>
				</Button>
			{:else}
				<div />
			{/if}

			<div class="flex flex-row gap-2 items-center justify-between">
				{#if $enterpriseLicense !== undefined}
					<Button
						color="dark"
						size="xs2"
						on:click={() => {
							migrationModal?.open()
						}}
					>
						Convert to global CSS
					</Button>
				{/if}
			</div>
		</div>

		<Tabs bind:selected={tab}>
			<Tab value="local" size="xs">
				<div class="flex flex-row gap-2 items-center">
					ID
					<Badge color="indigo" size="xs">
						{component?.id}
					</Badge>

					<Tooltip light>
						You can customise the CSS and the classes of this component instance. Theses
						customisations will only be applied to this component.
					</Tooltip>
				</div>
			</Tab>
			<Tab value="global" size="xs">
				<div class="flex flex-row gap-2 items-center">
					Global: {type ? ccomponents[type].name : ''}

					<Tooltip light>
						You can customise the CSS and the classes of all components of this type. Theses
						customisations will be applied to all components of this type.
					</Tooltip>
				</div>
			</Tab>
			<svelte:fragment slot="content">
				<TabContent value="local">
					{#if component && component.customCss !== undefined}
						{#each Object.keys(ccomponents[component.type].customCss ?? {}) as name}
							<div class="w-full">
								<CssProperty
									quickStyleProperties={quickStyleProperties?.[component.type]?.[name]}
									forceStyle={ccomponents[component.type].customCss[name].style !== undefined}
									forceClass={ccomponents[component.type].customCss[name].class !== undefined}
									tooltip={ccomponents[component.type].customCss[name].tooltip}
									{name}
									wmClass={getSelector(name)}
									componentType={component.type}
									bind:value={component.customCss[name]}
									on:change={() => app.set($app)}
									shouldDisplayRight={hasStyleValue(component.customCss[name])}
									on:right={() => {
										copyLocalToGlobal(name, component?.customCss?.[name])
										tab = 'global'
									}}
									overridding={hasStyleValue($app.css?.[component.type]?.[name]) &&
										hasStyleValue(component.customCss[name])}
								/>
							</div>
						{/each}
					{/if}
				</TabContent>
				<TabContent value="global">
					{#if type}
						{#each customCssByComponentType ?? [] as { id, forceStyle, forceClass }}
							<div class="w-full">
								{#if $app.css && type && $app.css[type] && component?.customCss}
									<CssPropertyWrapper
										{forceStyle}
										{forceClass}
										{id}
										bind:property={$app.css[type]}
										on:left={() => {
											copyGlobalToLocal(
												id,
												component?.type ? $app?.css?.[component?.type]?.[id] : undefined
											)
											tab = 'local'
										}}
										overriden={hasStyleValue(component.customCss[id])}
										wmClass={getSelector(id)}
									/>
								{/if}
							</div>
						{/each}
					{/if}
				</TabContent>
			</svelte:fragment>
		</Tabs>

		<ConfirmationModal
			title="Confirm overriding global CSS"
			confirmationText="Override global CSS"
			open={Boolean(overrideGlobalCSS)}
			on:confirmed={() => {
				if (overrideGlobalCSS) {
					overrideGlobalCSS()
					overrideGlobalCSS = undefined
				}

				sendUserToast('Global CSS overridden')
			}}
			on:canceled={() => {
				overrideGlobalCSS = undefined
			}}
		>
			<div class="text-primary pb-2">
				The global CSS for this component already exists. Do you want to override it?
			</div>
		</ConfirmationModal>

		<ConfirmationModal
			title="Confirm overriding local CSS"
			confirmationText="Override local CSS"
			open={Boolean(overrideLocalCSS)}
			on:confirmed={() => {
				if (overrideLocalCSS) {
					overrideLocalCSS()
					overrideLocalCSS = undefined
				}

				sendUserToast('Local CSS overridden')
			}}
			on:canceled={() => {
				overrideLocalCSS = undefined
			}}
		>
			<div class="text-primary pb-2">
				The local CSS for this component already exists. Do you want to override it?
			</div>
		</ConfirmationModal>
		<CssMigrationModal bind:this={migrationModal} bind:component />
	{/key}
{:else}
	<span class="text-sm text-secondary mx-2">Select a component to style it in this panel</span>
{/if}
