<template>
  <div class="flex flex-col bg-base-100 justify-center items-center gap-4">
    <!-- Title -->
    <h1 class="font-bold text-2xl">比特流文件</h1>

    <!-- 示例比特流下载区域 (仅在有examId时显示) -->
    <div v-if="examId && availableBitstreams.length > 0" class="w-full">
      <fieldset class="fieldset w-full">
        <legend class="fieldset-legend text-sm">示例比特流文件</legend>
        <div class="space-y-2">
          <div
            v-for="bitstream in availableBitstreams"
            :key="bitstream.id"
            class="flex items-center justify-between p-2 border-2 border-base-300 rounded-lg"
          >
            <span class="text-sm">{{ bitstream.name }}</span>
            <div class="flex gap-2">
              <button
                @click="downloadExampleBitstream(bitstream)"
                class="btn btn-sm btn-secondary"
                :disabled="isDownloading || isProgramming"
              >
                <div v-if="isDownloading">
                  <span class="loading loading-spinner loading-xs"></span>
                  {{ downloadProgress }}%
                </div>
                <div v-else>下载示例</div>
              </button>
              <button
                @click="programExampleBitstream(bitstream)"
                class="btn btn-sm btn-primary"
                :disabled="isDownloading || isProgramming"
              >
                <div v-if="isProgramming">
                  <span class="loading loading-spinner loading-xs"></span>
                  烧录中...
                </div>
                <div v-else>直接烧录</div>
              </button>
            </div>
          </div>
        </div>
      </fieldset>
    </div>

    <!-- 分割线 -->
    <div v-if="examId && availableBitstreams.length > 0" class="divider">
      或
    </div>

    <!-- Input File -->
    <fieldset class="fieldset w-full">
      <legend class="fieldset-legend text-sm">上传自定义比特流文件</legend>
      <input
        type="file"
        ref="fileInput"
        class="file-input w-full"
        @change="handleFileChange"
      />
      <label class="fieldset-label">文件最大容量: {{ maxMemory }}MB</label>
    </fieldset>

    <!-- Upload Button -->
    <div class="card-actions w-full">
      <button
        @click="handleClick"
        class="btn btn-primary grow"
        :disabled="isUploading || isProgramming"
      >
        <div v-if="isUploading">
          <span class="loading loading-spinner"></span>
          上传中...
        </div>
        <div v-else>上传并下载</div>
      </button>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { computed, ref, useTemplateRef, onMounted } from "vue";
import { AuthManager } from "@/utils/AuthManager"; // Adjust the path based on your project structure
import { useDialogStore } from "@/stores/dialog";
import { isNull, isUndefined } from "lodash";
import { useEquipments } from "@/stores/equipments";
import type { HubConnection } from "@microsoft/signalr";
import type {
  IProgressHub,
  IProgressReceiver,
} from "@/utils/signalR/TypedSignalR.Client/server.Hubs";
import {
  getHubProxyFactory,
  getReceiverRegister,
} from "@/utils/signalR/TypedSignalR.Client";
import { ProgressStatus } from "@/utils/signalR/server.Hubs";
import { useRequiredInjection } from "@/utils/Common";
import { useAlertStore } from "./Alert";

interface Props {
  maxMemory?: number;
  examId?: string; // 新增examId属性
}

const props = withDefaults(defineProps<Props>(), {
  maxMemory: 4,
  examId: "",
});

const emits = defineEmits<{
  finishedUpload: [file: File];
}>();

const alert = useRequiredInjection(useAlertStore);
const dialog = useDialogStore();
const eqps = useEquipments();

const isUploading = ref(false);
const isDownloading = ref(false);
const isProgramming = ref(false);
const availableBitstreams = ref<{ id: number; name: string }[]>([]);

// Progress
const downloadTaskId = ref("");
const downloadProgress = ref(0);
const progressHubConnection = ref<HubConnection>();
const progressHubProxy = ref<IProgressHub>();
const progressHubReceiver: IProgressReceiver = {
  onReceiveProgress: async (msg) => {
    if (msg.taskId == downloadTaskId.value) {
      if (msg.status == ProgressStatus.InProgress) {
        downloadProgress.value = msg.progressPercent;
      } else if (msg.status == ProgressStatus.Failed) {
        dialog.error(msg.errorMessage);
      } else if (msg.status == ProgressStatus.Completed) {
        alert.info("比特流下载成功");
      }
    }
  },
};
onMounted(async () => {
  progressHubConnection.value =
    AuthManager.createAuthenticatedProgressHubConnection();
  progressHubProxy.value = getHubProxyFactory("IProgressHub").createHubProxy(
    progressHubConnection.value,
  );
  getReceiverRegister("IProgressReceiver").register(
    progressHubConnection.value,
    progressHubReceiver,
  );
});

const fileInput = useTemplateRef("fileInput");
const bitstream = defineModel("bitstreamFile", {
  type: File,
  default: undefined,
});

// 初始化时加载示例比特流
onMounted(async () => {
  if (!isUndefined(bitstream.value) && !isNull(fileInput.value)) {
    let fileList = new DataTransfer();
    fileList.items.add(bitstream.value);
    fileInput.value.files = fileList.files;
  }

  await loadAvailableBitstreams();
});

// 加载可用的比特流文件列表
async function loadAvailableBitstreams() {
  console.log("加载可用比特流文件，examId:", props.examId);
  if (!props.examId) {
    availableBitstreams.value = [];
    return;
  }

  try {
    const resourceClient = AuthManager.createAuthenticatedResourceClient();
    // 使用新的ResourceClient API获取比特流模板资源列表
    const resources = await resourceClient.getResourceList(
      props.examId,
      "bitstream",
      "template",
    );
    availableBitstreams.value =
      resources.map((r) => ({ id: r.id, name: r.name })) || [];
  } catch (error) {
    console.error("加载比特流列表失败:", error);
    availableBitstreams.value = [];
  }
}

// 下载示例比特流
async function downloadExampleBitstream(bitstream: {
  id: number;
  name: string;
}) {
  if (isDownloading.value) return;

  isDownloading.value = true;
  try {
    const resourceClient = AuthManager.createAuthenticatedResourceClient();

    // 使用新的ResourceClient API获取资源文件
    const response = await resourceClient.getResourceById(bitstream.id);

    if (response && response.data) {
      // 创建下载链接
      const url = URL.createObjectURL(response.data);
      const link = document.createElement("a");
      link.href = url;
      link.download = response.fileName || bitstream.name;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      URL.revokeObjectURL(url);

      dialog.info("示例比特流下载成功");
    } else {
      dialog.error("下载失败：响应数据为空");
    }
  } catch (error) {
    console.error("下载示例比特流失败:", error);
    dialog.error("下载示例比特流失败");
  } finally {
    isDownloading.value = false;
  }
}

// 直接烧录示例比特流
async function programExampleBitstream(bitstream: {
  id: number;
  name: string;
}) {
  if (isProgramming.value) return;

  isProgramming.value = true;
  try {
    const downloadTaskId = await eqps.jtagDownloadBitstream(bitstream.id);
  } catch (error) {
    console.error("烧录示例比特流失败:", error);
    dialog.error("烧录示例比特流失败");
  } finally {
    isProgramming.value = false;
  }
}

function handleFileChange(event: Event): void {
  const target = event.target as HTMLInputElement;
  const file = target.files?.[0]; // 获取选中的第一个文件

  if (!file) {
    return;
  }

  bitstream.value = file;
}

function checkFile(file: File): boolean {
  const maxBytes = props.maxMemory! * 1024 * 1024; // 将最大容量从 MB 转换为字节
  if (file.size > maxBytes) {
    dialog.error(`文件大小超过最大限制: ${props.maxMemory}MB`);
    return false;
  }
  return true;
}

async function handleClick(event: Event): Promise<void> {
  console.log("上传按钮被点击");
  if (isNull(bitstream.value) || isUndefined(bitstream.value)) {
    dialog.error(`未选择文件`);
    return;
  }

  if (!checkFile(bitstream.value)) return;

  isUploading.value = true;
  let uploadedBitstreamId: number | null = null;
  try {
    console.log("开始上传比特流文件:", bitstream.value.name);
    const bitstreamId = await eqps.jtagUploadBitstream(
      bitstream.value,
      props.examId || "",
    );
    console.log("上传结果，ID:", bitstreamId);
    if (bitstreamId === null || bitstreamId === undefined) {
      isUploading.value = false;
      return;
    }
    uploadedBitstreamId = bitstreamId;
  } catch (e) {
    dialog.error("上传失败");
    console.error(e);
    return;
  }
  isUploading.value = false;

  // Download
  try {
    console.log("开始下载比特流，ID:", uploadedBitstreamId);
    if (uploadedBitstreamId === null || uploadedBitstreamId === undefined) {
      dialog.error("uploadedBitstreamId is null or undefined");
    } else {
      isDownloading.value = true;
      downloadTaskId.value =
        await eqps.jtagDownloadBitstream(uploadedBitstreamId);
    }
  } catch (e) {
    dialog.error("下载失败");
    console.error(e);
  }
}
</script>

<style scoped lang="postcss">
@import "../assets/main.css";
</style>
