<script lang="ts">
	import { createBubbler, preventDefault, stopPropagation } from 'svelte/legacy'

	const bubble = createBubbler()
	import type { Schema } from '$lib/common'
	import { VariableService, type ScriptLang } from '$lib/gen'
	import { workspaceStore } from '$lib/stores'
	import { Button } from './common'
	import ItemPicker from './ItemPicker.svelte'
	import VariableEditor from './VariableEditor.svelte'
	import { Pen, Plus, X } from 'lucide-svelte'
	import { Pane, Splitpanes } from 'svelte-splitpanes'
	import { twMerge } from 'tailwind-merge'
	import FlowPropertyEditor from './schema/FlowPropertyEditor.svelte'
	import PropertyEditor from './schema/PropertyEditor.svelte'
	import SimpleEditor from './SimpleEditor.svelte'
	import { createEventDispatcher, untrack } from 'svelte'
	import ToggleButton from './common/toggleButton-v2/ToggleButton.svelte'
	import ToggleButtonGroup from './common/toggleButton-v2/ToggleButtonGroup.svelte'
	import Label from './Label.svelte'
	import { sendUserToast } from '$lib/toast'
	import Toggle from './Toggle.svelte'
	import {
		DynamicInput,
		emptyString,
		generateRandomString,
		readFieldsRecursively
	} from '$lib/utils'
	import Popover from './meltComponents/Popover.svelte'
	import SchemaFormDnd from './schema/SchemaFormDND.svelte'
	import { deepEqual } from 'fast-equals'
	import { tweened } from 'svelte/motion'
	import type { SchemaDiff } from '$lib/components/schema/schemaUtils.svelte'
	import type { EditableSchemaFormUi } from '$lib/components/custom_ui'
	import Section from '$lib/components/Section.svelte'
	import Editor from './Editor.svelte'
	import AddPropertyV2 from './schema/AddPropertyV2.svelte'

	// export let openEditTab: () => void = () => {}
	const dispatch = createEventDispatcher()

	interface Props {
		schema: Schema | any
		hiddenArgs?: string[]
		args?: Record<string, any>
		shouldHideNoInputs?: boolean
		noVariablePicker?: boolean
		flexWrap?: boolean
		uiOnly?: boolean
		isFlowInput?: boolean
		noPreview?: boolean
		jsonEnabled?: boolean
		isAppInput?: boolean
		displayWebhookWarning?: boolean
		onlyMaskPassword?: boolean
		editTab:
			| 'inputEditor'
			| 'history'
			| 'savedInputs'
			| 'json'
			| 'captures'
			| 'firstStepInputs'
			| undefined
		previewSchema?: Record<string, any> | undefined
		editPanelInitialSize?: number | undefined
		editPanelSize?: number
		diff?: Record<string, SchemaDiff>
		disableDnd?: boolean
		shouldDispatchChanges?: boolean
		isValid?: boolean
		customUi?: EditableSchemaFormUi | undefined
		pannelExtraButtonWidth?: number
		class?: string
		dynCode?: string | undefined
		dynLang?: ScriptLang | undefined
		showDynOpt?: boolean
		addPropertyInEditorTab?: boolean
		openEditTab?: import('svelte').Snippet
		addProperty?: import('svelte').Snippet
		runButton?: import('svelte').Snippet
		extraTab?: import('svelte').Snippet
		schemaFormClassName?: string
		onChange?: (args: Record<string, any>) => void
	}

	let {
		schema = $bindable(),
		hiddenArgs = [],
		args = $bindable(undefined),
		shouldHideNoInputs = false,
		noVariablePicker = false,
		flexWrap = false,
		uiOnly = false,
		isFlowInput = false,
		noPreview = false,
		jsonEnabled = true,
		isAppInput = false,
		displayWebhookWarning = false,
		onlyMaskPassword = false,
		editTab,
		previewSchema = undefined,
		editPanelInitialSize = undefined,
		editPanelSize = $bindable(0),
		diff = {},
		disableDnd = false,
		shouldDispatchChanges = false,
		isValid = $bindable(true),
		customUi = undefined,
		pannelExtraButtonWidth = 0,
		class: clazz = '',
		dynCode = $bindable(),
		dynLang = $bindable(),
		showDynOpt = false,
		addPropertyInEditorTab = false,
		openEditTab,
		addProperty,
		runButton,
		extraTab,
		schemaFormClassName = undefined,
		onChange = undefined
	}: Props = $props()

	$effect.pre(() => {
		if (args == undefined) {
			args = {}
		}
		if (dynLang === undefined) {
			dynLang = schema?.['x-windmill-dyn-select-lang'] || 'bun'
		}
		if (dynCode === undefined) {
			dynCode = schema?.['x-windmill-dyn-select-code'] || ''
		}
	})

	$effect(() => {
		if (onChange) {
			readFieldsRecursively(args)
			onChange(args ?? {})
		}
	})

	$effect(() => {
		if (schema && dynCode !== undefined && dynLang !== undefined) {
			if (dynCode && dynCode.trim()) {
				schema['x-windmill-dyn-select-code'] = dynCode.trim()
				schema['x-windmill-dyn-select-lang'] = dynLang
			} else {
				delete schema['x-windmill-dyn-select-code']
				delete schema['x-windmill-dyn-select-lang']
			}
		}
	})

	export function setDefaults() {
		const nargs = {}

		Object.keys(schema?.properties ?? {}).forEach((key) => {
			if (schema?.properties[key].default != undefined && args?.[key] == undefined) {
				let value = schema?.properties[key].default
				nargs[key] = value === 'object' ? structuredClone($state.snapshot(value)) : value
			}
		})
		args = nargs
	}

	let pickForField: string | undefined
	let itemPicker: ItemPicker | undefined = $state(undefined)
	let variableEditor: VariableEditor | undefined = $state(undefined)

	let keys: string[] = $state(
		(Array.isArray(schema?.order)
			? [...schema.order]
			: (Object.keys(schema?.properties ?? {}) ?? Object.keys(schema?.properties ?? {}))
		).filter((x) => !hiddenArgs?.includes(x))
	)

	function alignOrderWithProperties(schema: {
		properties: Record<string, any>
		order: string[] | undefined
	}) {
		if (schema.order == undefined && !Array.isArray(schema.order)) {
			schema.order = []
		}
		let norder = [...schema.order]
		let properties = Object.keys(schema?.properties ?? {})
		let index = 0
		let hasChanged = false
		for (let k of properties) {
			if (schema.properties[k]?.type === 'object' && schema.properties[k].properties) {
				hasChanged = hasChanged || alignOrderWithProperties(schema.properties[k])
			}
			if (!norder.includes(k)) {
				norder = [...norder.slice(0, index), k, ...norder.slice(index)]
			}
			index += 1
		}
		norder = norder.filter((x) => properties.includes(x))
		if (!deepEqual(schema.order, norder)) {
			schema.order = norder
			return true
		}
		return hasChanged
	}
	function onSchemaChange() {
		if (alignOrderWithProperties(schema)) {
			// console.log('alignOrderWithProperties', JSON.stringify(schema, null, 2))
		}
		let lkeys = (schema?.order ?? Object.keys(schema?.properties ?? {})).filter(
			(x) => !hiddenArgs?.includes(x)
		)
		if (schema?.properties && !deepEqual(lkeys, keys)) {
			keys = [...lkeys]
			if (opened == undefined) {
				opened = keys[0]
			}
		}
	}

	let opened: string | undefined = $state(untrack(() => keys[0]))

	function computeSelected(property: any) {
		if (!opened) return ''
		if (property?.type !== 'object') return property?.type
		if (property.format === 'resource-s3_object') return 'S3'
		if (property.format?.startsWith('dynselect-')) return 'dynselect'
		if (property.format?.startsWith('dynmultiselect-')) return 'dynmultiselect'
		if (property.oneOf && property.oneOf.length >= 2) return 'oneOf'
		if (property.format?.startsWith('resource-')) return 'resource'
		return 'object'
	}

	export function openField(key: string) {
		opened = key
	}

	export function deleteField(key: string) {
		delete args?.[key]
		delete schema.properties[key]
		if (schema.required?.includes(key)) {
			schema.required = schema.required?.filter((x) => x !== key)
		}
		if (schema.order) {
			schema.order = schema.order.filter((x) => x !== key)
		}
	}

	function renameProperty(oldName: string, key: string) {
		const el = document.getElementById(key) as HTMLInputElement
		const newName = el.value
		if (oldName === newName) {
			return
		}

		if (Object.keys(schema.properties ?? {}).includes(newName)) {
			sendUserToast('There is already an argument with this name', true)

			// clear the input
			el.value = oldName
		} else {
			let newSchema = $state.snapshot(schema)
			if (args) {
				args[newName] = args[oldName]
				delete args[oldName]
			}

			newSchema.properties[newName] = newSchema.properties[oldName]
			delete newSchema.properties[oldName]

			if (newSchema.required?.includes(oldName)) {
				newSchema.required = newSchema.required?.map((x) => (x === oldName ? newName : x))
			}

			// Replace the old name with the new name in the order array
			if (newSchema.order) {
				const index = newSchema.order.indexOf(oldName)
				if (index !== -1) {
					newSchema.order[index] = newName
				}
			}

			opened = newName

			schema = newSchema

			sendUserToast('Argument renamed')
		}
	}

	let jsonView: boolean = $state(customUi?.jsonOnly == true)
	let schemaString: string = $state(JSON.stringify(schema, null, '\t'))
	let error: string | undefined = $state(undefined)
	let editor: SimpleEditor | undefined = $state(undefined)
	let dynamicSelectEditor: Editor | undefined = $state(undefined)
	export function updateJson() {
		schemaString = JSON.stringify(schema, null, '\t')
		editor?.setCode(schemaString)
	}

	const editTabDefaultSize = noPreview ? 100 : 50
	editPanelSize = editTab ? (editPanelInitialSize ?? editTabDefaultSize) : 0
	let inputPanelSize = $state(100 - editPanelSize)
	let editPanelSizeSmooth = tweened(editPanelSize, {
		duration: 150
	})
	let inputPanelSizeSmooth = tweened(
		untrack(() => inputPanelSize),
		{ duration: 150 }
	)

	function openEditTabFn() {
		if (editPanelSize > 0) return
		editPanelSizeSmooth.set(editTabDefaultSize)
		inputPanelSizeSmooth.set(100 - editTabDefaultSize)
	}

	function closeEditTab() {
		editPanelSizeSmooth.set(0)
		inputPanelSizeSmooth.set(100)
	}

	function updatePanelSizes(editSize: number, inputSize: number) {
		editPanelSize = editSize
		inputPanelSize = inputSize
		dispatch('editPanelSizeChanged', editSize)
	}

	let panelButtonWidth: number = $state(0)
	$effect(() => {
		if (args == undefined || typeof args !== 'object') {
			args = {}
		}
	})
	$effect(() => {
		schema && untrack(() => onSchemaChange())
	})
	$effect(() => {
		updatePanelSizes($editPanelSizeSmooth, $inputPanelSizeSmooth)
	})
	$effect(() => {
		!!editTab ? openEditTabFn() : closeEditTab()
	})

	let dynamicFunctions = $derived(
		Object.entries(schema?.properties ?? {})
			.filter(([_, property]) => {
				const props = property as any
				return props?.type === 'object' && DynamicInput.isDynInputFormat(props.format)
			})
			.map(([fieldName, _]) => fieldName.replace(/\s+/g, '_'))
	)

	const DYNAMIC_OPTIONS = [
		['DynSelect', 'dynselect'],
		['DynMultiselect', 'dynmultiselect']
	]

	let typeOptions = $state([
		['String', 'string'],
		['Number', 'number'],
		['Integer', 'integer'],
		['Boolean', 'boolean'],
		['Resource', 'resource'],
		['Object', 'object'],
		['OneOf', 'oneOf'],
		['Array', 'array'],
		['S3', 'S3']
	])

	function initDynFn(lang: ScriptLang) {
		const generateFn = DynamicInput.getGenerateTemplateFn(lang)
		return dynamicFunctions.map((functionName) => generateFn(functionName)).join('')
	}

	function updateDynCode(functionName: string, lang: ScriptLang = 'bun') {
		if (
			(lang == 'bun' && dynCode?.includes(`function ${functionName}`)) ||
			(lang == 'python3' && dynCode?.includes(`def ${functionName}`))
		) {
			// Don't add the function if it already exists
			return
		}

		const generateFn = DynamicInput.getGenerateTemplateFn(lang)
		const code = generateFn(functionName)
		dynCode = dynCode ? dynCode.concat(code) : code
	}

	let dndType = $state(generateRandomString())
</script>

<div class="w-full h-full">
	<div class="relative z-[100000]">
		<div
			class="absolute"
			style="right: calc({editPanelSize}% - 1px - {pannelExtraButtonWidth}px); top: 0px;"
			bind:clientWidth={panelButtonWidth}
		>
			{@render openEditTab?.()}
		</div>
	</div>
	<Splitpanes class="splitter-hidden w-full">
		{#if !noPreview}
			<Pane bind:size={inputPanelSize} minSize={20}>
				<div
					class="h-full flex flex-col gap-2 {openEditTab && editPanelSize > 0
						? 'pr-[38px]'
						: 'pr-2'}"
				>
					{#if addProperty}
						<div class="w-full justify-left pr-2 grow-0">
							<div
								style={editPanelSize > 0
									? `width: 100%;`
									: `width: calc(100% - ${panelButtonWidth - pannelExtraButtonWidth}px);`}
							>
								{@render addProperty?.()}
							</div>
						</div>
					{/if}

					<div
						class="min-h-0 overflow-y-auto grow rounded-md {runButton ? 'flex flex-col gap-2' : ''}"
					>
						<SchemaFormDnd
							{dndType}
							nestedClasses={'flex flex-col gap-1 ' + (schemaFormClassName ?? '')}
							bind:schema={
								() => (previewSchema ? previewSchema : schema),
								(newSchema) => {
									schema = newSchema
								}
							}
							{hiddenArgs}
							{disableDnd}
							{onlyMaskPassword}
							bind:args
							on:click={(e) => {
								opened = e.detail
							}}
							on:reorder={(e) => {
								let order = e.detail
								let newProperties = {}
								for (let key of order) {
									newProperties[key] = schema.properties[key]
								}
								schema = {
									...schema,
									properties: newProperties,
									order: e.detail
								}
							}}
							helperScript={{
								source: 'inline',
								code: dynCode!,
								lang: dynLang!
							}}
							prettifyHeader={isAppInput}
							disabled={!!previewSchema}
							{diff}
							on:acceptChange
							on:rejectChange
							{shouldDispatchChanges}
							bind:isValid
							noVariablePicker={noVariablePicker || customUi?.disableVariablePicker === true}
						/>

						{@render runButton?.()}

						{#if dynamicFunctions.length > 0}
							<Section
								label="Dynamic input functions"
								collapsable={true}
								collapsed={false}
								class="text-sm"
							>
								<div class="flex flex-col gap-2 h-full">
									{#if dynamicFunctions.length > 0}
										<div class="bg-blue-50 dark:bg-blue-900/20 p-3 rounded-md">
											<div class="text-sm font-semibold text-blue-800 dark:text-blue-200 mb-2">
												Expected Functions for Dynamic Input Fields:
											</div>
											<ul class="text-xs text-blue-700 dark:text-blue-300 space-y-1">
												{#each dynamicFunctions as functionName}
													<li class="font-mono bg-blue-100 dark:bg-blue-800/30 px-2 py-1 rounded">
														{functionName}()
													</li>
												{/each}
											</ul>
										</div>
									{/if}
									<ToggleButtonGroup
										bind:selected={dynLang}
										on:selected={({ detail }) => {
											dynCode = initDynFn(detail)
										}}
									>
										{#snippet children({ item })}
											<ToggleButton value="bun" label="Typescript (Bun)" {item} />
											<ToggleButton value="python3" label="Python" {item} />
										{/snippet}
									</ToggleButtonGroup>
									{#key dynLang}
										<div class="border w-full h-full">
											<Editor
												bind:this={dynamicSelectEditor}
												class="flex flex-1 grow h-80 w-full"
												scriptLang={dynLang}
												useWebsockets={false}
												automaticLayout
												bind:code={dynCode}
											/>
										</div>
									{/key}
								</div>
							</Section>
						{/if}
					</div>
				</div>
			</Pane>
		{/if}

		{#if editPanelSize > 0}
			<Pane
				bind:size={editPanelSize}
				minSize={noPreview ? 100 : 50}
				class={twMerge('border rounded-md', panelButtonWidth > 0 ? 'rounded-tl-none' : '')}
			>
				{#if editTab !== 'inputEditor'}
					{@render extraTab?.()}
				{:else}
					<!-- WIP -->
					{#if jsonEnabled && customUi?.jsonOnly != true}
						<div class="w-full px-4 py-2 flex gap-4 justify-end items-center">
							{#if addPropertyInEditorTab}
								<AddPropertyV2
									bind:schema
									onAddNew={(propertyName) => {
										openField(propertyName)
									}}
								>
									{#snippet trigger()}
										<Button variant="subtle" size="xs" iconOnly startIcon={{ icon: Plus }} />
									{/snippet}
								</AddPropertyV2>
							{/if}
							<div class="shrink-0">
								<Toggle
									bind:checked={jsonView}
									size="xs"
									options={{
										left: 'JSON editor',
										leftTooltip:
											'Arguments can be edited either using the wizard, or by editing their JSON Schema.'
									}}
									lightMode
									on:change={(e) => {
										if (e.detail) {
											schemaString = JSON.stringify(schema, null, '\t')
											editor?.setCode(schemaString)
										} else {
											schema = JSON.parse(schemaString)
										}
									}}
								/>
							</div>
						</div>
					{/if}

					{#if !jsonView}
						<div
							class="w-full {clazz} {flexWrap ? 'flex flex-row flex-wrap gap-x-6 ' : ''} divide-y"
						>
							{#if keys.length > 0}
								{#each keys as argName, i (argName)}
									<div>
										<!-- svelte-ignore a11y_click_events_have_key_events -->
										<!-- svelte-ignore a11y_no_static_element_interactions -->
										<div
											class={twMerge(
												'w-full flex bg-gray-50 dark:bg-gray-800 px-4 py-1 justify-between items-center hover:bg-gray-100 cursor-pointer',
												opened === argName ? 'bg-gray-100 hover:bg-gray-200' : ''
											)}
											onclick={() => {
												if (opened === argName) {
													opened = undefined
												} else {
													opened = argName
												}
											}}
										>
											<div class="flex flex-row gap-2 text-sm">
												{argName}
												{#if !uiOnly}
													<div onclick={stopPropagation(preventDefault(bubble('click')))}>
														<Popover placement="bottom-end" containerClasses="p-4" closeButton>
															{#snippet trigger()}
																<Button
																	variant="subtle"
																	size="xs3"
																	nonCaptureEvent
																	startIcon={{ icon: Pen }}
																	iconOnly
																/>
															{/snippet}
															{#snippet content({ close })}
																<Label label="Name" class="p-4">
																	<div class="flex flex-col gap-2">
																		<input
																			type="text"
																			class="w-full !bg-surface"
																			value={argName}
																			id={argName + i}
																			onkeydown={(event) => {
																				if (event.key === 'Enter') {
																					renameProperty(argName, argName + i)
																					close()
																				}
																			}}
																		/>
																		<Button
																			variant="default"
																			size="xs"
																			on:click={() => {
																				renameProperty(argName, argName + i)
																				close()
																			}}
																		>
																			Rename
																		</Button>
																	</div>
																</Label>
															{/snippet}
														</Popover>
													</div>
												{/if}
											</div>

											{#if schema.required?.includes(argName)}
												<span class="text-red-500 text-xs"> Required </span>
											{/if}

											{#if !uiOnly}
												<button
													class="delete-schema-field-button
													rounded-full p-1 text-gray-500 bg-white
				duration-200 hover:bg-gray-600 focus:bg-gray-600 hover:text-white dark:bg-gray-700 dark:text-white dark:hover:bg-gray-800"
													aria-label="Clear"
													onclick={() => {
														dispatch('delete', argName)
													}}
												>
													<X size={16} />
												</button>
											{/if}
										</div>
										{#if opened === argName}
											<div class="p-4 border-t">
												{#if Object.keys(schema?.properties ?? {}).includes(argName)}
													{#if typeof args == 'object' && schema?.properties[argName]}
														<PropertyEditor
															bind:description={schema.properties[argName].description}
															type={schema.properties[argName]?.type}
															bind:oneOf={schema.properties[argName].oneOf}
															bind:pattern={schema.properties[argName].pattern}
															bind:enum_={schema.properties[argName].enum}
															bind:format={schema.properties[argName].format}
															bind:contentEncoding={schema.properties[argName].contentEncoding}
															bind:customErrorMessage={
																schema.properties[argName].customErrorMessage
															}
															bind:nonEmpty={schema.properties[argName].nonEmpty}
															bind:itemsType={schema.properties[argName].items}
															bind:extra={schema.properties[argName]}
															bind:title={schema.properties[argName].title}
															bind:placeholder={schema.properties[argName].placeholder}
															bind:properties={schema.properties[argName].properties}
															bind:order={schema.properties[argName].order}
															{isFlowInput}
															{isAppInput}
														>
															{#snippet typeeditor()}
																{#if isFlowInput || isAppInput}
																	<Label label="Type">
																		<ToggleButtonGroup
																			tabListClass="flex-wrap"
																			class="h-auto"
																			bind:selected={
																				() => computeSelected(schema.properties[opened ?? '']),
																				(v) => {
																					const isResource = v == 'resource'
																					const isS3 = v == 'S3'
																					const isOneOf = v == 'oneOf'
																					const isDynSelect = v == 'dynselect'
																					const isDynMultiselect = v == 'dynmultiselect'
																					const emptyProperty = {
																						contentEncoding: undefined,
																						enum_: undefined,
																						pattern: undefined,
																						default: undefined,
																						min: undefined,
																						max: undefined,
																						currency: undefined,
																						currencyLocale: undefined,
																						multiselect: undefined,
																						password: undefined,
																						dateFormat: undefined,
																						...(v == 'array' ? { items: { type: 'string' } } : {}),
																						showExpr: undefined,
																						nullable: undefined,
																						required: undefined
																					}

																					if (
																						isDynMultiselect &&
																						args &&
																						!Array.isArray(args?.[argName])
																					) {
																						args[argName] = []
																					}

																					if (isS3) {
																						schema.properties[argName] = {
																							...emptyProperty,
																							type: 'object',
																							format: 'resource-s3_object'
																						}
																					} else if (isResource) {
																						schema.properties[argName] = {
																							...emptyProperty,
																							type: 'object',
																							format: 'resource-'
																						}
																					} else if (isDynSelect || isDynMultiselect) {
																						const functionName = argName.replace(/\s+/g, '_')
																						schema.properties[argName] = {
																							...emptyProperty,
																							type: 'object',
																							format:
																								(isDynSelect ? 'dynselect-' : 'dynmultiselect-') +
																								functionName
																						}
																						updateDynCode(argName, dynLang)
																						dynamicSelectEditor?.setCode(dynCode || '')
																					} else if (isOneOf) {
																						schema.properties[argName] = {
																							...emptyProperty,
																							type: 'object',
																							oneOf: [
																								{
																									title: 'Option 1',
																									type: 'object',
																									properties: {
																										label: {
																											type: 'string',
																											enum: ['Option 1']
																										},
																										property_1: {
																											type: 'string'
																										}
																									},
																									order: ['property_1']
																								},
																								{
																									title: 'Option 2',
																									type: 'object',
																									properties: {
																										label: {
																											type: 'string',
																											enum: ['Option 2']
																										},
																										property_2: {
																											type: 'string'
																										}
																									},
																									order: ['property_2']
																								}
																							]
																						}
																					} else {
																						schema.properties[argName] = {
																							...emptyProperty,
																							format: undefined,
																							type: v
																						}
																					}
																					schema.properties = schema.properties
																				}
																			}
																		>
																			{#snippet children({ item })}
																				{#each typeOptions as x}
																					<ToggleButton value={x[1]} label={x[0]} {item} />
																				{/each}
																				{#if showDynOpt}
																					{#each DYNAMIC_OPTIONS as x}
																						<ToggleButton value={x[1]} label={x[0]} {item} />
																					{/each}
																				{/if}
																			{/snippet}
																		</ToggleButtonGroup>
																	</Label>
																{/if}
															{/snippet}

															{#if isFlowInput || isAppInput}
																<FlowPropertyEditor
																	onDrawerClose={() => {
																		dndType = generateRandomString()
																	}}
																	bind:defaultValue={schema.properties[argName].default}
																	{variableEditor}
																	{itemPicker}
																	bind:nullable={schema.properties[argName].nullable}
																	bind:disabled={schema.properties[argName].disabled}
																	type={schema.properties[argName]?.type}
																	bind:oneOf={schema.properties[argName].oneOf}
																	bind:format={schema.properties[argName].format}
																	contentEncoding={schema.properties[argName].contentEncoding}
																	required={schema.required?.includes(argName) ?? false}
																	pattern={schema.properties[argName].pattern}
																	password={schema.properties[argName].password}
																	propsNames={schema.properties[argName].propsNames}
																	bind:showExpr={schema.properties[argName].showExpr}
																	extra={schema.properties[argName]}
																	customErrorMessage={schema.properties[argName].customErrorMessage}
																	itemsType={schema.properties[argName].items}
																	bind:properties={schema.properties[argName].properties}
																	bind:order={schema.properties[argName].order}
																	bind:requiredProperty={schema.properties[argName].required}
																	{displayWebhookWarning}
																	on:requiredChange={(event) => {
																		if (event.detail.required) {
																			schema.required = schema.required ?? []
																			schema.required.push(argName)
																		} else {
																			schema.required = schema.required?.filter(
																				(x) => x !== argName
																			)
																		}
																	}}
																/>
															{/if}
														</PropertyEditor>
													{/if}
												{/if}
											</div>
										{/if}
									</div>
								{/each}
							{:else if !shouldHideNoInputs}
								<div class="text-secondary text-xs p-2">No inputs</div>
							{/if}
						</div>
					{:else}
						<div class="p-2">
							<div class="border rounded h-full">
								<SimpleEditor
									bind:this={editor}
									small
									fixedOverflowWidgets={false}
									on:change={() => {
										try {
											schema = JSON.parse(schemaString)
											error = ''
										} catch (err) {
											error = err.message
										}
									}}
									bind:code={schemaString}
									lang="json"
									autoHeight
									automaticLayout
								/>
							</div>
							{#if !emptyString(error)}
								<div class="text-red-400 text-xs">{error}</div>
							{:else}
								<div><br /> </div>
							{/if}
						</div>
					{/if}
				{/if}
			</Pane>
		{/if}
	</Splitpanes>
</div>

{#if !noVariablePicker}
	<ItemPicker
		bind:this={itemPicker}
		pickCallback={(path, _) => {
			if (pickForField) {
				if (args) {
					args[pickForField] = '$var:' + path
				}
			}
		}}
		itemName="Variable"
		tooltip="Variables are dynamic values that have a key associated to them and can be retrieved during the execution of a Script or Flow."
		documentationLink="https://www.windmill.dev/docs/core_concepts/variables_and_secrets"
		extraField="path"
		loadItems={async () =>
			(await VariableService.listVariable({ workspace: $workspaceStore ?? '' })).map((x) => ({
				name: x.path,
				...x
			}))}
	>
		{#snippet submission()}
			<div>
				<Button
					variant="default"
					size="sm"
					startIcon={{ icon: Plus }}
					on:click={() => variableEditor?.initNew?.()}
				>
					New variable
				</Button>
			</div>
		{/snippet}
	</ItemPicker>

	<VariableEditor bind:this={variableEditor} />
{/if}

<style>
	:global(.splitter-hidden .splitpanes__splitter) {
		background-color: transparent !important;
		border: none !important;
		opacity: 0 !important;
	}
</style>
