<script lang="ts" setup>
import { computed, watch } from 'vue'

import NodeRuntimeConfig from '@/nodes/_base/NodeRuntimeConfig.vue'
import VarSelect from '@/nodes/_base/VarSelect.vue'
import { useSetterModel } from '../_shared/useSetterModel'
import { useI18n } from '@/composables/useI18n'
import { filterArrayVariables } from '../utils'

import type { IterationData } from './index'
import type { NodeVariable, NodeVariableType } from '@/nodes/Interface'

const outputsTypeMap = {
	string: 'array[string]',
	number: 'array[number]',
	boolean: 'array[boolean]',
	object: 'array[object]',
	'array[string]': 'array[object]',
	'array[number]': 'array[object]',
	'array[boolean]': 'array[object]',
	'array[object]': 'array[object]'
}

const props = defineProps<{
	data: IterationData
}>()

const emit = defineEmits<{
	update: [data: IterationData]
}>()

const { t } = useI18n()

const texts = computed(() => ({
	input: t('pages.iterationSetter.input'),
	output: t('pages.iterationSetter.output'),
	selectInput: t('pages.iterationSetter.selectInput'),
	parallelMode: t('pages.iterationSetter.parallelMode'),
	maxParallel: t('pages.iterationSetter.maxParallel'),
	maxParallelTip: t('pages.iterationSetter.maxParallelTip'),
	errorHandling: t('pages.iterationSetter.errorHandling'),
	flattenOutput: t('pages.iterationSetter.flattenOutput'),
	stop: t('pages.iterationSetter.stop'),
	continueOnError: t('pages.iterationSetter.continueOnError'),
	removeAbnormal: t('pages.iterationSetter.removeAbnormal')
}))

const errorHandleModeOptions = computed(() => [
	{ label: texts.value.stop, value: 'terminated' },
	{ label: texts.value.continueOnError, value: 'continue-on-error' },
	{ label: texts.value.removeAbnormal, value: 'remove-abnormal-output' }
])

const formData = useSetterModel<IterationData>(props, emit)

const inputVar = computed({
	get() {
		return formData.value.variables?.[0]
	},
	set(val) {
		if (val && formData.value.variables?.[0]) {
			formData.value.variables[0] = val
		} else if (val) {
			formData.value.variables = [val]
		} else {
			formData.value.variables = []
		}
	}
})

const outputIterationVar = computed({
	get() {
		return formData.value.output_iteration_variable
	},
	set(val) {
		formData.value.output_iteration_variable =
			val || ({ name: '', type: '', value: '' } as unknown as NodeVariable)
	}
})

const handleInputVarChange = (val: { value: string; type: NodeVariableType }) => {
	inputVar.value = {
		name: 'iteration_input',
		value: val.value,
		type: val.type
	}
}

const handleInputVarClear = () => {
	inputVar.value = undefined
}

const handleOutputIterationVarChange = (val: { value: string; type: NodeVariableType }) => {
	outputIterationVar.value = {
		name: '',
		value: val.value,
		type: val.type
	}
}

const handleOutputIterationVarClear = () => {
	outputIterationVar.value = {
		name: '',
		value: '',
		type: ''
	} as unknown as NodeVariable
}

watch(
	() => formData.value.output_iteration_variable?.type,
	(val) => {
		if (val) {
			if (formData.value.outputs?.[0]) {
				formData.value.outputs[0].type = outputsTypeMap[
					val as keyof typeof outputsTypeMap
				] as NodeVariableType
			} else {
				formData.value.outputs = [
					{
						name: 'outputs',
						type: outputsTypeMap[val as keyof typeof outputsTypeMap] as NodeVariableType
					}
				]
			}
		} else {
			formData.value.outputs = []
		}
	}
)
</script>

<template>
	<el-scrollbar class="w-full box-border p-12px">
		<el-form label-width="50px">
			<el-form-item label="" label-position="top">
				<div class="w-full flex items-center justify-between beautify">
					<label class="text-14px font-bold text-gray-700">{{ texts.input }}</label>
				</div>
				<VarSelect
					:model-value="inputVar?.value"
					:var-type="inputVar?.type"
					:placeholder="texts.selectInput"
					:filter-fn="filterArrayVariables"
					@change="handleInputVarChange"
					@clear="handleInputVarClear"
				/>
			</el-form-item>

			<el-form-item label="" label-position="top">
				<div class="w-full flex items-center justify-between beautify">
					<label class="text-14px font-bold text-gray-700">{{ texts.output }}</label>
				</div>
				<VarSelect
					:model-value="outputIterationVar?.value"
					:var-type="outputIterationVar?.type"
					:placeholder="texts.selectInput"
					@change="handleOutputIterationVarChange"
					@clear="handleOutputIterationVarClear"
				/>
			</el-form-item>

			<el-form-item label="" label-position="top">
				<div class="w-full flex items-center justify-between beautify">
					<label class="text-14px font-bold text-gray-700">{{ texts.parallelMode }}</label>
					<el-switch v-model="formData.is_parallel" />
				</div>
			</el-form-item>

			<el-form-item
				v-if="formData.is_parallel"
				:label="texts.maxParallel"
				:tooltip="texts.maxParallelTip"
				label-position="top"
			>
				<div class="w-full flex gap-12px pr-12px">
					<el-input-number v-model="formData.parallel_nums" :min="1" :max="10" />
					<div class="flex-2/3">
						<el-slider v-model="formData.parallel_nums" :min="1" :max="10" />
					</div>
				</div>
			</el-form-item>

			<el-form-item label="" label-position="top">
				<div class="w-full flex items-center justify-between beautify">
					<label class="text-14px font-bold text-gray-700">{{ texts.errorHandling }}</label>
				</div>
				<el-select v-model="formData.error_handle_mode" :options="errorHandleModeOptions" />
			</el-form-item>

			<el-form-item label="" label-position="top">
				<div class="w-full flex items-center justify-between beautify">
					<label class="text-14px font-bold text-gray-700">{{ texts.flattenOutput }}</label>
					<el-switch v-model="formData.flatten_output" />
				</div>
			</el-form-item>

			<NodeRuntimeConfig v-model="formData" />
		</el-form>
	</el-scrollbar>
</template>
