<template>
  <div class="value-editor">
    <div class="value-editor-content">
      <!-- 字符串编辑器 -->
      <a-input
        v-if="type === 'string'"
        v-model:value="localValue"
        placeholder="请输入字符串"
        @change="updateValue"
        class="value-input"
      />
      
      <!-- 数字编辑器 -->
      <a-input-number
        v-else-if="type === 'number'"
        v-model:value="localNumberValue"
        placeholder="请输入数字"
        @change="updateValue"
        class="value-input"
      />
      
      <!-- 布尔编辑器 -->
      <a-switch
        v-else-if="type === 'boolean'"
        v-model:checked="localBoolValue"
        @change="updateValue"
        class="boolean-input"
      />
      
      <!-- 对象编辑器 -->
      <key-value-editor
        v-else-if="type === 'object'"
        v-model:modelValue="localObjectValue"
        @update:modelValue="updateValue"
        :forceOneLevel="forceOneLevel"
        class="object-input"
      />
      
      <!-- 数组编辑器 -->
      <array-editor
        v-else-if="type === 'array'"
        v-model:modelValue="localArrayValue"
        @update:modelValue="updateValue"
        :forceOneLevel="forceOneLevel"
        class="array-input"
      />
      
      <!-- null编辑器 -->
      <div v-else-if="type === 'null'" class="null-editor">
        <span class="null-value">null</span>
      </div>
    </div>
    <div class="value-editor-type-selector">
      <a-dropdown>
        <a-button type="text" class="type-select-button">
          {{ type }}
          <down-outlined />
        </a-button>
        <template #overlay>
          <a-menu>
            <a-menu-item key="string" @click="changeType('string')">字符串</a-menu-item>
            <a-menu-item key="number" @click="changeType('number')">数字</a-menu-item>
            <a-menu-item key="boolean" @click="changeType('boolean')">布尔</a-menu-item>
            <a-menu-item key="object" v-if="!forceOneLevel" @click="changeType('object')">对象</a-menu-item>
            <a-menu-item key="array" v-if="!forceOneLevel" @click="changeType('array')">数组</a-menu-item>
            <a-menu-item key="null" @click="changeType('null')">null</a-menu-item>
          </a-menu>
        </template>
      </a-dropdown>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, watch, computed } from 'vue';
import { DownOutlined } from '@ant-design/icons-vue';
import KeyValueEditor from './KeyValueEditor.vue';
import ArrayEditor from './ArrayEditor.vue';

const props = defineProps<{
  modelValue?: any;
  /**
   * 这会限制用户只能创建简单的值，而不能嵌套对象或数组。
   * @default false
   */
  forceOneLevel?: boolean;
}>();
const emit = defineEmits<{
  (e: 'update:modelValue', value: any): void;
}>();

export type LocalItemType = 'string' | 'number' | 'boolean' | 'object' | 'array' | 'null';

// 计算当前值的类型
const type = computed<LocalItemType>(() => {
  const value = props.modelValue;
  if (value === null) {
    return 'null';
  } else if (typeof value === 'string') {
    return 'string';
  } else if (typeof value === 'number') {
    return 'number';
  } else if (typeof value === 'boolean') {
    return 'boolean';
  } else if (Array.isArray(value)) {
    return 'array';
  } else if (typeof value === 'object') {
    return 'object';
  } else {
    return 'string';
  }
});

// 本地值
const localValue = ref<string>(props.modelValue as string || '');
const localNumberValue = ref<number>(typeof props.modelValue === 'number' ? props.modelValue : 0);
const localBoolValue = ref<boolean>(!!props.modelValue);
const localObjectValue = ref<Record<string, any>>(props.modelValue as Record<string, any> || {});
const localArrayValue = ref<any[]>(props.modelValue as any[] || []);

// 监听props变化
watch(
  () => props.modelValue,
  (newValue) => {
    if (type.value === 'string') {
      localValue.value = newValue as string || '';
    } else if (type.value === 'number') {
      localNumberValue.value = typeof newValue === 'number' ? newValue : 0;
    } else if (type.value === 'boolean') {
      localBoolValue.value = !!newValue;
    } else if (type.value === 'object') {
      localObjectValue.value = newValue as Record<string, any> || {};
    } else if (type.value === 'array') {
      localArrayValue.value = newValue as any[] || [];
    }
  },
  { deep: true, immediate: true }
);

// 更新值
const updateValue = () => {
  let value: any;
  
  if (type.value === 'string') {
    value = localValue.value;
  } else if (type.value === 'number') {
    value = localNumberValue.value;
  } else if (type.value === 'boolean') {
    value = localBoolValue.value;
  } else if (type.value === 'object') {
    value = localObjectValue.value;
  } else if (type.value === 'array') {
    value = localArrayValue.value;
  } else if (type.value === 'null') {
    value = null;
  } else {
    value = localValue.value;
  }
  
  emit('update:modelValue', value);
};

// 更改类型
const changeType = (newType: LocalItemType) => {
  let newValue: any;
  
  switch (newType) {
    case 'string':
      newValue = '' + (props.modelValue || '');
      break;
    case 'number':
      newValue = Number(props.modelValue) || 0;
      break;
    case 'boolean':
      newValue = false;
      break;
    case 'object':
      newValue = JSON.parse(JSON.stringify(props.modelValue)) || {};
      break;
    case 'array':
      newValue = JSON.parse(JSON.stringify(props.modelValue)) || [];
      break;
    case 'null':
      newValue = null;
      break;
    default:
      newValue = '';
  }
  emit('update:modelValue', newValue);
};
</script>

<style scoped>
.value-editor {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 8px;
  border-radius: 4px;
  border: 1px dashed #e8e8e8;
}

.value-editor-content {
  flex: 1;
  min-width: 0;
}

.value-input {
  width: 100%;
}

.boolean-input {
  margin: 4px 0;
}

.object-input,
.array-input {
  width: 100%;
}

.null-editor {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 4px 0;
}

.null-value {
  color: #999;
  font-style: italic;
}

.value-editor-type-selector {
  white-space: nowrap;
}

.type-select-button {
  min-width: 80px;
  text-align: center;
}
</style>