<script lang="ts">
	import { getContext } from 'svelte'
	import type { AppEditorContext, AppViewerContext } from '../types'
	import { columnConfiguration, isFixed, toggleFixed } from '../gridUtils'
	import { twMerge } from 'tailwind-merge'

	import RecomputeAllComponents from './RecomputeAllComponents.svelte'
	import type { Policy } from '$lib/gen'
	import HiddenComponent from '../components/helpers/HiddenComponent.svelte'
	import Component from './component/Component.svelte'
	import { push } from '$lib/history'
	import { dfs, expandGriditem, findGridItem } from './appUtils'
	import Grid from '../svelte-grid/Grid.svelte'
	import { deepEqual } from 'fast-equals'
	import ComponentWrapper from './component/ComponentWrapper.svelte'
	import { classNames } from '$lib/utils'
	import Toggle from '$lib/components/Toggle.svelte'
	import Tooltip from '$lib/components/Tooltip.svelte'
	import { BG_PREFIX } from '../utils'

	export let policy: Policy

	const {
		selectedComponent,
		app,
		mode,
		connectingInput,
		summary,
		focusedGrid,
		parentWidth,
		breakpoint,
		allIdsInPath
	} = getContext<AppViewerContext>('AppViewerContext')

	const { history } = getContext<AppEditorContext>('AppEditorContext')

	let previousSelectedIds: string[] | undefined = undefined
	$: if (!deepEqual(previousSelectedIds, $selectedComponent)) {
		previousSelectedIds = $selectedComponent
		$allIdsInPath = ($selectedComponent ?? [])
			.flatMap((id) => dfs($app.grid, id, $app.subgrids ?? {}))
			.filter((x) => x != undefined) as string[]
	}
</script>

<div class="relative w-full z-20 overflow-visible">
	<div
		class="w-full sticky top-0 flex justify-between border-b {$connectingInput?.opened
			? ''
			: 'bg-surface'} px-4 py-1 items-center gap-4"
		style="z-index: 1000;"
	>
		<h3 class="truncate">{$summary}</h3>
		{#if !$connectingInput.opened}
			<RecomputeAllComponents />
		{/if}
		<div class="flex text-2xs gap-8 items-center">
			<div class="py-2 pr-2 text-secondary flex gap-1 items-center">
				Hide bar on view
				<Toggle size="xs" bind:checked={$app.norefreshbar} />
			</div>
			<div>
				{policy.on_behalf_of ? `Author ${policy.on_behalf_of_email}` : ''}
				<Tooltip
					>The scripts will be run on behalf of the author and a tight policy ensure security about
					the possible inputs of the runnables.</Tooltip
				>
			</div>
		</div>
	</div>

	<!-- svelte-ignore a11y-click-events-have-key-events -->
	<div
		style={$app.css?.['app']?.['grid']?.style}
		class={twMerge('px-4 pt-4 pb-2 overflow-visible', $app.css?.['app']?.['grid']?.class ?? '')}
		on:pointerdown={() => {
			$selectedComponent = undefined
			$focusedGrid = undefined
		}}
		bind:clientWidth={$parentWidth}
	>
		<div class={!$focusedGrid && $mode !== 'preview' ? ' border border-dashed' : ''}>
			<Grid
				allIdsInPath={$allIdsInPath}
				selectedIds={$selectedComponent}
				items={$app.grid}
				on:redraw={(e) => {
					push(history, $app)
					$app.grid = e.detail
				}}
				let:dataItem
				rowHeight={36}
				cols={columnConfiguration}
				fastStart={true}
				gap={[4, 2]}
			>
				<ComponentWrapper
					id={dataItem.id}
					type={dataItem.data.type}
					class={classNames(
						'h-full w-full center-center outline outline-surface-secondary',
						Boolean($selectedComponent?.includes(dataItem.id)) ? 'active-grid-item' : ''
					)}
				>
					<Component
						render={true}
						component={dataItem.data}
						selected={Boolean($selectedComponent?.includes(dataItem.id))}
						locked={isFixed(dataItem)}
						on:lock={() => {
							const gridItem = findGridItem($app, dataItem.id)
							if (gridItem) {
								toggleFixed(gridItem)
							}
							$app = $app
						}}
						on:expand={() => {
							push(history, $app)
							$selectedComponent = [dataItem.id]
							expandGriditem($app.grid, dataItem.id, $breakpoint)
							$app = $app
						}}
					/>
				</ComponentWrapper>
			</Grid>
		</div>
	</div>
</div>

{#if $app.hiddenInlineScripts}
	{#each $app.hiddenInlineScripts as runnable, index}
		{#if runnable}
			<HiddenComponent id={BG_PREFIX + index} {runnable} />
		{/if}
	{/each}
{/if}

<style global>
	.svlt-grid-shadow {
		/* Back shadow */
		background: #93c4fdd0 !important;
	}
	.svlt-grid-active {
		opacity: 1 !important;
	}
</style>
