<template>
  <div class="advanced-config-container">
    <div class="advnce-config">
      <label class="text-ellipsis-multiple">是否渲染</label>
      <div class="advanced-config-form-item">
        <switch-configurator v-if="!isBind" :modelValue="condition" @update:modelValue="setConfig">
        </switch-configurator>
        <div v-else class="binding-state text-ellipsis-multiple" :title="condition.value">
          已绑定:{{ condition.value }}
        </div>
        <variable-configurator
          v-model="condition"
          name="advance"
          @update:modelValue="setConfig"
        ></variable-configurator>
      </div>
    </div>

    <div class="advnce-config loop-data-item">
      <label class="text-ellipsis-multiple">循环数据</label>
      <div class="advanced-config-form-item">
        <code-configurator
          v-if="!state.isLoop"
          v-model="state.loopData"
          data-type="JSExpression"
          @update:modelValue="setLoop"
          @open="openEditor"
        ></code-configurator>
        <div v-else class="binding-state text-ellipsis-multiple" :title="state.loopData?.value">
          已绑定:{{ state.loopData?.value }}
        </div>
        <variable-configurator
          v-model="state.loopData"
          name="advance"
          @update:modelValue="setLoop"
        ></variable-configurator>
      </div>
    </div>
    <div class="advnce-config">
      <label class="text-ellipsis-multiple">迭代变量名</label>
      <div class="advanced-config-form-item">
        <input-configurator
          v-model="state.loopItem"
          :placeholder="`默认值为:${DEFAULT_LOOP_NAME.ITEM}`"
          @update:modelValue="setLoopItem"
        ></input-configurator>
      </div>
    </div>
    <div class="advnce-config">
      <label class="text-ellipsis-multiple">索引变量名</label>
      <div class="advanced-config-form-item">
        <input-configurator
          v-model="state.loopIndex"
          :placeholder="`默认值为:${DEFAULT_LOOP_NAME.INDEX}`"
          @update:modelValue="setLoopIndex"
        ></input-configurator>
      </div>
    </div>
    <div class="advnce-config">
      <label class="text-ellipsis-multiple">key</label>
      <div class="advanced-config-form-item">
        <tiny-tooltip content="建议填写循环项中的唯一值(如item.id),如果填写为数字将不保存" effect="light">
          <input-configurator
            v-model="state.loopKey"
            :placeholder="`默认为索引名:${getIndexName()}`"
            @update:modelValue="setLoopKey"
          ></input-configurator>
        </tiny-tooltip>
      </div>
    </div>
  </div>
</template>

<script lang="ts">
/* metaService: engine.setting.event.AdvanceConfig */
import { ref, computed, reactive, watch } from 'vue'
import type { Component } from 'vue'
import {
  CodeConfigurator,
  InputConfigurator,
  SwitchConfigurator,
  VariableConfigurator
} from '@opentiny/tiny-engine-configurator'
import { useProperties, useCanvas } from '@opentiny/tiny-engine-meta-register'
import { PROP_DATA_TYPE } from '@opentiny/tiny-engine-common/js/constants'
import { constants, utils } from '@opentiny/tiny-engine-utils'
import { Tooltip } from '@opentiny/vue'

const { DEFAULT_LOOP_NAME } = constants
const { string2Obj } = utils

export default {
  components: {
    SwitchConfigurator,
    TinyTooltip: Tooltip as Component,
    VariableConfigurator,
    InputConfigurator,
    CodeConfigurator
  },
  inheritAttrs: false,
  setup() {
    const { pageState } = useCanvas()
    const condition = ref(false)
    const isBind = computed(() => condition.value?.type === PROP_DATA_TYPE.JSEXPRESSION)
    const getIndexName = () => useProperties().getSchema()?.loopArgs?.[1] || DEFAULT_LOOP_NAME.INDEX

    const state = reactive({
      loopData: {
        type: PROP_DATA_TYPE.JSEXPRESSION,
        value: '[]'
      },
      loopItem: 'item',
      loopIndex: 'index',
      isLoop: computed(() => state.loopData?.type === PROP_DATA_TYPE.JSEXPRESSION),
      loopKey: '',
      shouldUpdate: false
    })

    watch(
      () => [pageState?.currentSchema, state.shouldUpdate],
      ([value]) => {
        condition.value = value?.condition === undefined ? true : value?.condition
        state.loopData = value?.loop
        state.loopItem = value?.loopArgs?.[0] || ''
        state.loopIndex = value?.loopArgs?.[1] || ''
        state.loopKey = value?.props?.key?.value || ''
      }
    )

    const setLoopKey = (value = '') => {
      value = value.replace(/\s*/g, '')
      const { getSchema, setProp } = useProperties()
      const schema = getSchema()

      if (!schema) {
        return
      }

      const isNumber = Number(value).toString() !== 'NaN'
      let newPropsKey = schema.props?.key

      if (value && !isNumber) {
        newPropsKey = {
          type: PROP_DATA_TYPE.JSEXPRESSION,
          value
        }
      }

      if (!value) {
        if (state.isLoop) {
          newPropsKey = {
            type: PROP_DATA_TYPE.JSEXPRESSION,
            value: getIndexName()
          }
        } else {
          newPropsKey = ''
        }
      }

      setProp('key', newPropsKey)
    }

    watch([() => state.isLoop, () => state.loopIndex], () => {
      if (!state.loopKey && state.isLoop) {
        setLoopKey(getIndexName())
      }

      if (!state.isLoop) {
        setLoopKey('')
      }
    })

    const openEditor = () => {
      state.loopData = useProperties().getSchema()?.loop
    }

    const setConfig = (value) => {
      const { getSchema } = useProperties()
      const schema = getSchema()

      if (!schema) {
        return
      }

      const { operateNode } = useCanvas()

      if (value === false || value?.type) {
        operateNode({ type: 'updateAttributes', id: schema.id, value: { condition: value } })
      } else {
        const { condition: _schemaCondition, children, ...rest } = schema
        operateNode({ type: 'updateAttributes', id: schema.id, value: { ...rest }, overwrite: true })
      }

      useCanvas().canvasApi.value.updateRect()
      condition.value = value
    }

    const setLoopIndex = (value) => {
      const schema = useProperties().getSchema()
      let loopArgs = schema.loopArgs
      const { operateNode } = useCanvas()

      if (loopArgs) {
        loopArgs[1] = value || DEFAULT_LOOP_NAME.INDEX
      } else {
        loopArgs = [DEFAULT_LOOP_NAME.ITEM, value]
      }

      operateNode({ type: 'updateAttributes', id: schema.id, value: { loopArgs } })
    }

    const setLoop = (value) => {
      const { operateNode } = useCanvas()
      const { getSchema } = useProperties()
      const schema = getSchema()

      if (value) {
        const newLoop = value?.type ? value : string2Obj(value)

        operateNode({ type: 'updateAttributes', id: schema.id, value: { loop: newLoop } })
        setLoopIndex(DEFAULT_LOOP_NAME.INDEX)
      } else {
        setLoopKey()
        const { loop: _loop, loopArgs: _loopArgs, children: _children, ...rest } = schema

        operateNode({ type: 'updateAttributes', id: schema.id, value: rest, overwrite: true })
      }

      // 触发更新state
      state.shouldUpdate = !state.shouldUpdate
    }

    const setLoopItem = (value) => {
      const schema = useProperties().getSchema()
      let loopArgs = schema.loopArgs
      const { operateNode } = useCanvas()

      if (loopArgs) {
        loopArgs[0] = value || DEFAULT_LOOP_NAME.ITEM
      } else {
        loopArgs = [value, DEFAULT_LOOP_NAME.INDEX]
      }

      operateNode({ type: 'updateAttributes', id: schema.id, value: { loopArgs } })
    }

    return {
      condition,
      setConfig,
      isBind,
      state,
      setLoop,
      setLoopItem,
      DEFAULT_LOOP_NAME,
      openEditor,
      setLoopIndex,
      setLoopKey,
      getIndexName
    }
  }
}
</script>

<style lang="less" scoped>
.advanced-config-container {
  .advnce-config {
    &:not(:last-child) {
      margin-bottom: var(--te-common-vertical-item-spacing-normal);
    }
    align-items: center;
    display: flex;
    column-gap: 12px;
    color: var(--te-events-advanced-config-text-color);

    label {
      width: 80px;
      word-break: keep-all;
      color: var(--te-events-advanced-label-text-color);
      flex-shrink: 0;
    }

    .advanced-config-form-item {
      display: grid;
      grid-template-columns: 1fr auto;
      flex: 1;
    }
    .binding-state {
      box-sizing: border-box;
      background: var(--te-events-advanced-binding-state-bg-color);
      color: var(--te-events-advanced-binding-state-text-color);
      border: 1px solid var(--te-events-advanced-binding-state-border-color);
      font-size: 12px;
      height: 24px;
      line-height: 14px;
      padding: 4px 8px;
      --ellipsis-line: 1;
      border-radius: var(--te-base-border-radius-1);
    }

    .advance-config-loop-wrap {
      .advance-item {
        width: 100%;
      }
    }
  }
  .loop-data-item {
    display: block;
    label {
      margin-bottom: 5px;
    }
  }
}
</style>