// filepath: c:\_Project\FPGA_WebLab\FPGA_WebLab\src\components\equipments\Switch.vue
<template>
  <svg 
    xmlns="http://www.w3.org/2000/svg" 
    :width="width" 
    :height="height" 
    :viewBox="`4 6 ${props.switchCount + 2} 4`"
    class="dip-switch"
  >
    <defs>
      <filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
        <feFlood result="flood" flood-color="#f08a5d" flood-opacity="1"></feFlood>
        <feComposite in="flood" result="mask" in2="SourceGraphic" operator="in"></feComposite>
        <feMorphology in="mask" result="dilated" operator="dilate" radius="0.02"></feMorphology>
        <feGaussianBlur in="dilated" stdDeviation="0.05" result="blur1" />
        <feGaussianBlur in="dilated" stdDeviation="0.1" result="blur2" />
        <feGaussianBlur in="dilated" stdDeviation="0.2" result="blur3" />
        <feMerge>
          <feMergeNode in="blur3" />
          <feMergeNode in="blur2" />
          <feMergeNode in="blur1" />
          <feMergeNode in="SourceGraphic" />
        </feMerge>
      </filter>
    </defs>
    
    <g>
      <!-- 红色背景随开关数量变化宽度 -->
      <rect :width="props.switchCount + 2" height="4" x="4" y="6" fill="#c01401" rx="0.1" />
      <text v-if="props.showLabels" fill="white" font-size="0.7" x="4.25" y="6.75">ON</text>
      
      <g>
        <template v-for="(_, index) in Array(props.switchCount)" :key="index">
          <rect 
            class="glow interactive" 
            @click="toggleBtnStatus(index)" 
            width="0.7" 
            height="2" 
            fill="#68716f" 
            :x="5.15 + index" 
            y="7" 
            rx="0.1" 
          />
          <text 
            v-if="props.showLabels"
            :x="5.5 + index" 
            y="9.5" 
            font-size="0.4" 
            text-anchor="middle"
            fill="#444"
          >
            {{ index + 1 }}
          </text>
        </template>
      </g>
      
      <g>
        <template v-for="(location, index) in btnLocation" :key="`btn-${index}`">
          <rect 
            class="interactive"
            @click="toggleBtnStatus(index)" 
            width="0.65" 
            height="0.65" 
            fill="white" 
            :x="5.175 + index" 
            :y="location" 
            rx="0.1"
            opacity="1" 
          />
        </template>
      </g>
    </g>
  </svg>
</template>

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

interface Props {
  size?: number;
  switchCount?: number;
  // 新增属性
  initialValues?: boolean[] | string; // 开关的初始状态，可以是布尔数组或逗号分隔的字符串
  showLabels?: boolean;      // 是否显示标签
}

const props = withDefaults(defineProps<Props>(), {
  size: 1,
  switchCount: 6,
  initialValues: () => [],
  showLabels: true
});

// 计算实际宽高
const width = computed(() => {
  // 每个开关占用25px宽度，再加上两侧边距(20px)
  return (props.switchCount * 25 + 20) * props.size;
});
const height = computed(() => 85 * props.size); // 高度保持固定比例

// 定义发出的事件
const emit = defineEmits(['change', 'switch-toggle']);

// 解析初始值，支持字符串和数组两种格式
const parseInitialValues = () => {
  if (Array.isArray(props.initialValues)) {
    return [...props.initialValues].slice(0, props.switchCount);
  } else if (typeof props.initialValues === 'string' && props.initialValues.trim() !== '') {
    // 将逗号分隔的字符串转换为布尔数组
    const values = props.initialValues.split(',')
      .map(val => val.trim() === '1' || val.trim().toLowerCase() === 'true')
      .slice(0, props.switchCount);
    
    // 如果数组长度小于开关数量，用 false 填充
    while (values.length < props.switchCount) {
      values.push(false);
    }
    
    return values;
  }
  // 默认返回全部为 false 的数组
  return Array(props.switchCount).fill(false);
};

// 初始化按钮状态
const btnStatus = ref(parseInitialValues());

// 监听 switchCount 变化，调整开关状态数组
watch(() => props.switchCount, (newCount) => {
  if (newCount !== btnStatus.value.length) {
    // 如果新数量大于当前数量，则扩展数组
    if (newCount > btnStatus.value.length) {
      btnStatus.value = [
        ...btnStatus.value,
        ...Array(newCount - btnStatus.value.length).fill(false)
      ];
    } else {
      // 如果新数量小于当前数量，则截断数组
      btnStatus.value = btnStatus.value.slice(0, newCount);
    }
  }
}, { immediate: true });

// 监听 initialValues 变化，更新开关状态
watch(() => props.initialValues, () => {
  btnStatus.value = parseInitialValues();
});

const btnLocation = computed(() => {
  return btnStatus.value.map((status) => {
    return status ? 7.025 : 8.325;
  });
});

function setBtnStatus(btnNum: number, isOn: boolean): void {
  if (btnNum >= 0 && btnNum < btnStatus.value.length) {
    btnStatus.value[btnNum] = isOn;
    emit('change', { index: btnNum, value: isOn, states: [...btnStatus.value] });
  }
}

function toggleBtnStatus(btnNum: number): void {
  if (btnNum >= 0 && btnNum < btnStatus.value.length) {
    btnStatus.value[btnNum] = !btnStatus.value[btnNum];
    emit('switch-toggle', { 
      index: btnNum, 
      value: btnStatus.value[btnNum], 
      states: [...btnStatus.value] 
    });
  }
}

// 一次性设置所有开关状态
function setAllStates(states: boolean[]): void {
  const newStates = states.slice(0, props.switchCount);
  while (newStates.length < props.switchCount) {
    newStates.push(false);
  }
  btnStatus.value = newStates;
  emit('change', { states: [...btnStatus.value] });
}

// 暴露组件方法和状态
defineExpose({
  setBtnStatus,
  toggleBtnStatus,
  setAllStates,
  getBtnStatus: () => [...btnStatus.value]
});
</script>

<style scoped lang="postcss">
.dip-switch {
  display: block;
  padding: 0;
  margin: 0;
  line-height: 0; /* 移除行高导致的额外间距 */
  font-size: 0; /* 防止文本节点造成的间距 */
  box-sizing: content-box;
  overflow: visible;
}

rect {
  transition: all 100ms ease-in-out;
}

.interactive {
  cursor: pointer;
}
</style>
