<template>
  <div>
    <div class="card m-5 bg-base-200 shadow-2xl">
      <div class="card-body">
        <h2 class="card-title flex justify-between items-center">
          <div class="flex items-center gap-2">
            <Zap class="w-5 h-5" />
            调试器波形捕获
          </div>
          <div class="flex items-center gap-2">
            <button
              class="btn btn-sm btn-primary"
              @click="
                () => {
                  handleDeleteData();
                  startCapture();
                }
              "
              :disabled="!captureData"
            >
              重新捕获
            </button>
            <button
              class="btn btn-sm btn-error"
              @click="handleDeleteData"
              :disabled="!captureData"
            >
              清空
            </button>
          </div>
        </h2>
        <WaveformDisplay :data="captureData">
          <div class="text-center">
            <h3 class="text-xl font-semibold text-slate-600 mb-2">
              暂无逻辑分析数据
            </h3>
            <p class="text-sm text-slate-500">点击下方按钮开始捕获</p>
          </div>
          <button
            class="group relative px-8 py-3 bg-gradient-to-r text-white font-medium rounded-lg shadow-lg hover:shadow-xl transform hover:scale-105 transition-all duration-200 ease-in-out focus:outline-none focus:ring-4 active:scale-95"
            :class="{
              'from-blue-500 to-purple-600 hover:from-blue-600 hover:to-purple-700 focus:ring-blue-300':
                !isCapturing,
              'from-red-500 to-red-600 hover:from-red-600 hover:to-red-700 focus:ring-red-300':
                isCapturing,
            }"
            @click="isCapturing ? stopCapture() : startCapture()"
          >
            <span class="flex items-center gap-2">
              <template v-if="isCapturing">
                <Square class="w-5 h-5" />
                停止捕获
              </template>
              <template v-else>
                <Play class="w-5 h-5" />
                开始捕获
              </template>
            </span>
          </button>
        </WaveformDisplay>
      </div>
    </div>
    <!-- Debugger 通道配置 -->
    <div class="card m-5 bg-base-200 shadow-2xl">
      <div class="card-body">
        <div class="flex justify-between">
          <h2 class="card-title mb-4">调试器通道配置</h2>
          <div class="flex items-center gap-2">
            <button
              class="btn btn-sm btn-primary"
              @click="addChannel"
              :disabled="!configInited"
            >
              添加通道
            </button>
            <button
              class="btn btn-sm btn-secondary"
              @click="showConfigDialog = true"
            >
              配置
            </button>
          </div>
        </div>
        <!-- 配置未初始化时 -->
        <div
          v-if="!configInited"
          class="flex flex-col items-center justify-center py-10"
        >
          <div class="text-lg text-slate-500 mb-4">请先进行调试器基本配置</div>
          <button class="btn btn-primary" @click="showConfigDialog = true">
            配置调试器
          </button>
        </div>

        <div v-if="configInited" class="overflow-x-auto flex flex-col gap-10">
          <!-- 状态概览 -->
          <div
            class="stats stats-horizontal bg-base-100 shadow flex justify-between"
          >
            <div class="stat">
              <div class="stat-title">启用端口数</div>
              <div class="stat-value text-primary">
                {{ config.totalPortNum }}
              </div>
              <div class="stat-desc">每端口最大32线</div>
            </div>
            <div class="stat">
              <div class="stat-title">最大线宽数</div>
              <div class="stat-value text-info">
                {{ config.totalPortNum * 32 }}
              </div>
              <div class="stat-desc">启用端口数 × 32</div>
            </div>
            <div class="stat">
              <div class="stat-title">已用线宽数</div>
              <div class="stat-value text-success">
                {{ channels.reduce((sum, ch) => sum + ch.width, 0) }}
              </div>
              <div class="stat-desc">所有通道线宽总和</div>
            </div>
            <div class="stat">
              <div class="stat-title">采样深度</div>
              <div class="stat-value text-warning">
                {{ config.captureDepth }}
              </div>
              <div class="stat-desc">每通道采样点数</div>
            </div>
            <div class="stat">
              <div class="stat-title">时钟频率</div>
              <div class="stat-value text-accent">{{ config.clkFreq }} MHz</div>
              <div class="stat-desc">采样时钟</div>
            </div>
          </div>

          <!-- 通道表格 -->
          <div class="space-y-2">
            <!-- 表头 -->
            <div
              class="grid grid-cols-7 justify-items-center gap-2 p-2 bg-base-300 rounded-lg text-sm font-medium"
            >
              <span>名称</span>
              <span>显示</span>
              <span>颜色</span>
              <span>触发模式</span>
              <span>数据位宽(起始:结尾)</span>
              <span>父端口编号</span>
              <span>操作</span>
            </div>
            <!-- 通道列表 -->
            <div
              v-for="(ch, idx) in channels"
              :key="idx"
              class="grid grid-cols-7 place-items-center gap-4 p-4 bg-base-200 rounded-lg hover:bg-base-300 transition-colors"
            >
              <input
                v-model="ch.name"
                class="input input-bordered w-full"
                :placeholder="`通道${idx + 1}`"
              />
              <input
                type="checkbox"
                v-model="ch.visible"
                class="toggle toggle-primary"
              />
              <input
                type="color"
                v-model="ch.color"
                class="w-8 h-8 rounded border-2 border-base-300 cursor-pointer"
              />
              <select
                v-model="ch.trigger"
                class="select select-bordered w-full"
              >
                <option
                  v-for="mode in triggerModes"
                  :key="mode.value"
                  :value="mode.value"
                >
                  {{ mode.label }}
                </option>
              </select>
              <input
                v-model="ch.widthStr"
                class="input input-bordered w-full"
                placeholder="如0:7"
                @change="parseWidthStr(idx)"
              />
              <input
                type="number"
                min="0"
                :max="config.totalPortNum - 1"
                v-model.number="ch.parentPort"
                class="input input-bordered w-full"
              />
              <button class="btn btn-error" @click="removeChannel(idx)">
                删除
              </button>
            </div>
            <!-- 添加通道按钮 -->
            <div class="flex justify-center mt-2">
              <button class="btn btn-primary w-100" @click="addChannel">
                添加通道
              </button>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 配置Dialog -->
    <dialog v-if="showConfigDialog" class="modal modal-open">
      <form
        method="dialog"
        class="modal-box max-w-fit"
        @submit.prevent="onConfigSubmit"
      >
        <h3 class="font-bold text-lg mb-4">调试器基本配置</h3>
        <div class="flex flex-col gap-4 w-80">
          <BaseInputField
            v-model="config.clkFreq"
            label="时钟频率 (MHz)"
            type="number"
            min="1"
            max="200"
            :error="
              config.clkFreq < 1 || config.clkFreq > 500 ? '范围1~200' : ''
            "
            required
          />
          <BaseInputField
            v-model="config.totalPortNum"
            label="启用端口数"
            type="number"
            min="1"
            max="16"
            :error="
              config.totalPortNum < 1 || config.totalPortNum > 16
                ? '范围1~16'
                : ''
            "
            required
          />
          <BaseInputField
            v-model="config.captureDepth"
            label="采样深度"
            type="number"
            min="1"
            max="1048576"
            :error="
              config.captureDepth < 1 || config.captureDepth > 1048576
                ? '范围1~1048576'
                : ''
            "
            required
          />
        </div>
        <div class="modal-action mt-6">
          <button class="btn btn-primary" type="submit">确定</button>
          <button class="btn" type="button" @click="showConfigDialog = false">
            取消
          </button>
        </div>
      </form>
    </dialog>
  </div>
</template>

<script setup lang="ts">
import { CaptureMode, ChannelConfig, DebuggerConfig } from "@/APIClient";
import { useAlertStore } from "@/components/Alert";
import BaseInputField from "@/components/InputField/BaseInputField.vue";
import type { LogicDataType } from "@/components/WaveformDisplay";
import WaveformDisplay from "@/components/WaveformDisplay/WaveformDisplay.vue";
import { AuthManager } from "@/utils/AuthManager";
import { useRequiredInjection } from "@/utils/Common";
import { useLocalStorage } from "@vueuse/core";
import axios, { type CancelTokenSource } from "axios";
import { isNull } from "lodash";
import { Play, Square, Zap } from "lucide-vue-next";
import { ref, reactive, computed } from "vue";

interface DebugChannel {
  name: string;
  visible: boolean;
  color: string;
  trigger: CaptureMode;
  width: number;
  widthStr: string;
  start: number;
  parentPort: number;
}

interface DebuggerSettings {
  clkFreq: number;
  totalPortNum: number;
  captureDepth: number;
}

const triggerModes = [
  { value: CaptureMode.None, label: "x (无关)" },
  { value: CaptureMode.Logic0, label: "0 (低电平)" },
  { value: CaptureMode.Logic1, label: "1 (高电平)" },
  { value: CaptureMode.Rise, label: "↑ (上升沿)" },
  { value: CaptureMode.Fall, label: "↓ (下降沿)" },
];

// 基本配置
const config = reactive<DebuggerSettings>({
  clkFreq: 50,
  totalPortNum: 1,
  captureDepth: 1024,
});
const configInited = ref(false);
const showConfigDialog = ref(false);

function onConfigSubmit() {
  configInited.value = true;
  showConfigDialog.value = false;
  // 清空通道
  channels.value = [];
}

// 通道配置
const channels = useLocalStorage<DebugChannel[]>("debugger-channels", []);
const captureData = ref<LogicDataType>();
const alert = useRequiredInjection(useAlertStore);

const isCapturing = ref(false);
const readCancelTokenSource = ref<CancelTokenSource | null>(null);

// 解析widthStr为start/width
function parseWidthStr(idx: number) {
  const ch = channels.value[idx];
  const match = /^(\d+)\s*:\s*(\d+)$/.exec(ch.widthStr);
  if (isNull(match)) {
    alert.error("格式错误，应为 起始位:宽度，如 0:7");
    ch.widthStr = `${ch.start}:${ch.width}`;
    return;
  }

  const min = Math.min(parseInt(match[1]), parseInt(match[2]));
  const max = Math.max(parseInt(match[1]), parseInt(match[2]));

  ch.start = min;
  ch.width = max - min + 1;
}

function addChannel() {
  if (!configInited.value) {
    alert.error("请先配置调试器基本参数");
    return;
  }
  if (channels.value.length >= config.totalPortNum * 32) {
    alert.error("通道数已达最大线宽数");
    return;
  }
  channels.value.push({
    name: `CH${channels.value.length + 1}`,
    visible: true,
    color: "#00bcd4",
    trigger: CaptureMode.None,
    width: 1,
    widthStr: "0:0",
    start: 0,
    parentPort: 0,
  });
}

function removeChannel(idx: number) {
  channels.value.splice(idx, 1);
}

function handleDeleteData() {
  captureData.value = undefined;
}

function stopCapture() {
  isCapturing.value = false;
  if (readCancelTokenSource.value) {
    readCancelTokenSource.value.cancel("用户手动停止捕获");
    readCancelTokenSource.value = null;
  }
}

async function startCapture() {
  if (!configInited.value) {
    alert.error("请先配置调试器基本参数");
    return;
  }
  if (channels.value.length === 0) {
    alert.error("请至少添加一个通道");
    return;
  }

  // 校验通道参数
  let usedWires = 0;
  for (let i = 0; i < channels.value.length; i++) {
    const ch = channels.value[i];
    if (!ch.visible) continue;
    if (!ch.name) {
      alert.error(`通道 ${i + 1} 名称不能为空`);
      return;
    }
    if (ch.width < 1 || ch.width > 32) {
      alert.error(`通道 ${i + 1} 数据位宽必须在1到32之间`);
      return;
    }
    if (ch.start < 0 || ch.start + ch.width > 32) {
      alert.error(`通道 ${i + 1} 起始位+宽度不能超过32`);
      return;
    }
    if (ch.parentPort < 0 || ch.parentPort >= config.totalPortNum) {
      alert.error(`通道 ${i + 1} 父端口编号超出范围`);
      return;
    }
    usedWires += ch.width;
  }
  if (usedWires > config.totalPortNum * 32) {
    alert.error("所有通道线宽总和不能超过最大线宽数");
    return;
  }

  isCapturing.value = true;
  const client = AuthManager.createAuthenticatedDebuggerClient();

  // 构造API配置
  const channelConfigs = channels.value
    .filter((ch) => ch.visible)
    .map(
      (ch) =>
        new ChannelConfig({
          name: ch.name,
          color: ch.color,
          wireWidth: ch.width,
          wireStartIndex: ch.start,
          parentPort: ch.parentPort,
          mode: ch.trigger,
        }),
    );

  const apiConfig = new DebuggerConfig({
    clkFreq: config.clkFreq,
    totalPortNum: config.totalPortNum,
    captureDepth: config.captureDepth,
    triggerNum: 0,
    channelConfigs: channelConfigs,
  });

  try {
    // 设置通道模式
    let ret = await client.setChannelsMode(apiConfig);
    if (!ret) {
      alert.error("设置通道模式失败");
      isCapturing.value = false;
      return;
    }

    // 启动捕获
    ret = await client.startTrigger();
    if (!ret) {
      alert.error("开始捕获失败，请检查连接");
      isCapturing.value = false;
      return;
    }

    // 读取数据
    readCancelTokenSource.value = axios.CancelToken.source();
    const readDataPromise = client
      .readData(apiConfig, readCancelTokenSource.value.token)
      .then((data) => {
        const enabledChannels = channelConfigs;
        const sampleCount = config.captureDepth;

        // 解析数据
        const y = data.map((cd, idx) => {
          const ch = enabledChannels[idx];
          const bin = atob(cd.data);
          // UInt32数组
          const arr = [];
          for (let i = 0; i < bin.length; i += 4) {
            arr.push(
              bin.charCodeAt(i) |
                (bin.charCodeAt(i + 1) << 8) |
                (bin.charCodeAt(i + 2) << 16) |
                (bin.charCodeAt(i + 3) << 24),
            );
          }
          // 截取采样深度
          return {
            enabled: true,
            type: ch.wireWidth === 1 ? ("logic" as const) : ("number" as const),
            name: ch.name,
            color: ch.color,
            value: arr.slice(0, sampleCount),
            base: ch.wireWidth === 1 ? ("bin" as const) : ("hex" as const),
          };
        });

        const x: number[] = [];
        for (let i = 0; i < sampleCount; i++) {
          x.push(i * (1 / config.clkFreq)); // us
        }

        captureData.value = {
          x,
          y,
          xUnit: "us",
        };
      })
      .catch((error) => {
        if (axios.isCancel(error)) {
          alert.info("捕获已取消");
        } else {
          alert.error(`读取数据失败: ${error.message}`);
        }
      })
      .finally(() => {
        isCapturing.value = false;
        readCancelTokenSource.value = null;
      });
  } catch (error: any) {
    alert.error(`开始捕获失败: ${error.message}`);
    isCapturing.value = false;
    return;
  }
}
</script>
