<template>
  <DesktopView :peerId="sign2peerid(targetId)" />
  <div class="container">
    <!-- 连接状态 -->
    <div class="status-bar">
      <div class="peer-info">
        {{ $t("index.myId") }}:
        <span class="id-text">{{
          myId || $t("index.waitingForConnection")
        }}</span>
        <Button type="primary" @click="copyId" v-if="myId">{{
          $t("index.copy")
        }}</Button>
        <Button type="link" @click="shareUrl" v-if="myId">{{
          $t("index.share")
        }}</Button>
        <span
          v-if="connectedPeerId"
          class="connection-badge"
          :class="{ inbound: isInboundConnected }"
        >
          {{
            isInboundConnected
              ? $t("index.connectedBy")
              : $t("index.connected")
          }}:
          <span class="connected-peer">{{ connectedPeerLabel }}</span>
          <Button
            v-if="isInboundConnected && connectedPeerSign"
            type="link"
            size="small"
            @click="copyPeerSign"
            >{{ $t("index.copy") }}</Button
          >
        </span>
      </div>
      <!-- 显示流量 丢包率-->
      <div class="status-info">
        <div class="status-item">
          <span>{{ $t("index.traffic") }}:</span>
          <span>{{ formatSize(transInfo.bytes) }}/s</span>
        </div>
        <div class="status-item">
          <span>{{ $t("index.packets") }}:</span>
          <span>{{ transInfo.packets }}/s</span>
        </div>
      </div>

      <div class="status-actions">
        <div class="connect-section">
          <div class="connect-actions">
            <div
              class="connect-item"
              :class="{ disabled: !isConnected, active: isDesktopActive }"
              :title="$t('index.desktopPreview')"
              @click="requestDesktop"
            >
              <img
                src="/static/desktop.png"
                :alt="$t('index.desktopPreview')"
              />
            </div>
            <div
              class="connect-item"
              :class="{ disabled: !isConnected, active: isCallActive }"
              :title="$t('index.voiceCall')"
              @click="requestCall"
            >
              <img src="/static/phone.png" :alt="$t('index.voiceCall')" />
            </div>
            <div
              class="connect-item"
              :class="{ disabled: !isConnected, active: isCameraActive }"
              :title="$t('index.camera')"
              @click="requestCamera"
            >
              <svg
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
              >
                <path d="M23 7l-7 5 7 5V7z" />
                <rect x="1" y="5" width="15" height="14" rx="2" />
              </svg>
            </div>
          </div>
          <input
            v-model="targetId"
            :placeholder="
              !myId ? $t('common.pleaseWait') : $t('index.enterPeerId')
            "
            :disabled="isConnected || !myId"
          />
          <Button
            @click="handleConnect"
            :disabled="!targetId || isConnected"
            :loading="isConnecting"
          >
            {{ isConnected ? $t("index.connectedBtn") : $t("index.connect") }}
          </Button>
        </div>
        <a-dropdown>
          <div class="lang-switcher">
            <svg
              t="1778484837023"
              class="icon lang-switcher-icon"
              viewBox="0 0 1024 1024"
              version="1.1"
              xmlns="http://www.w3.org/2000/svg"
              p-id="1747"
            >
              <path
                d="M846.04 866.77c-17.08 2.03-32.57-10.18-34.59-27.26-0.22-1.9-0.27-3.81-0.15-5.71v-123c0-33.73-22.17-33.73-30.53-33.73-21.28-0.46-38.91 16.43-39.36 37.72-0.01 0.46-0.01 0.92 0 1.37v117.66c-0.76 18.9-16.71 33.61-35.61 32.84-17.83-0.72-32.12-15.01-32.84-32.84V647.68c-1.23-17.23 11.74-32.19 28.97-33.41 1.69-0.12 3.39-0.1 5.08 0.05a31.953 31.953 0 0 1 31.33 17.76 89.435 89.435 0 0 1 54.99-17.76c54.11 0 86.45 33.59 86.45 90.03V833.8a32.25 32.25 0 0 1-8.88 23.72 34.026 34.026 0 0 1-24.82 9.33l-0.04-0.08z m-233.12-7.46h-134.7c-42.77 0-61.85-18.96-61.85-61.57V608.07c0-42.52 19.09-61.57 61.85-61.57h128.74c17.92 0 32.45 14.53 32.45 32.45s-14.53 32.45-32.45 32.45H490.73c-1.22-0.08-2.45 0.09-3.6 0.5 0.13 0-0.15 0.8-0.15 2.89v52.58h106c16.33-1.66 30.91 10.24 32.57 26.57 0.17 1.68 0.2 3.37 0.08 5.06 0.98 16.66-11.73 30.97-28.4 31.95-1.41 0.08-2.83 0.07-4.24-0.05H486.9V791c-0.04 1.06 0.08 2.13 0.35 3.15 1.12 0.15 2.25 0.23 3.38 0.24h122.31c16.96-1.07 31.58 11.81 32.65 28.76 0.07 1.16 0.08 2.33 0.02 3.5 1.35 16.68-11.07 31.3-27.75 32.65-1.64 0.13-3.28 0.13-4.92 0h-0.02zM327.54 482.85c-17.36 2.36-33.34-9.8-35.7-27.16-0.3-2.21-0.37-4.44-0.2-6.67V370.5h-85.27c-45.86 0-66.31-20.52-66.31-66.31v-93.87c0-45.58 20.52-65.9 66.31-65.9h85.27v-31.53c-1.38-17.11 11.37-32.11 28.48-33.49 1.92-0.15 3.84-0.13 5.76 0.07 30.26 0 36.63 18.17 36.63 33.42v31.59h86.09c45.86 0 66.33 20.34 66.33 65.88v93.89c0 45.86-20.52 66.29-66.33 66.29h-86.05v78.52c1.25 17.47-11.9 32.65-29.37 33.91-1.88 0.13-3.76 0.1-5.63-0.1v-0.02zM217.21 211.27c-6.47 0-7.07 0.6-7.07 7.07v78.2c0 6.53 0.6 7.15 7.07 7.15h74.43v-92.42h-74.43z m145.35 92.38h75.29c6.29 0 7.09-0.8 7.09-7.07v-78.25c0-6.29-0.8-7.09-7.09-7.09h-75.31v92.42h0.02z m151.42 655.91C266.43 958.82 66.36 757.55 67.1 510c0.1-35 4.31-69.86 12.52-103.88 4.81-19 23.92-30.68 43.03-26.29 19.1 4.61 30.86 23.81 26.29 42.91-48.93 202.33 75.42 406.01 277.75 454.94a376.924 376.924 0 0 0 87.29 10.56c19.69 0.02 35.64 15.99 35.63 35.69-0.02 19.67-15.96 35.61-35.63 35.63z m398.49-310.05c-19.69 0-35.66-15.96-35.66-35.65 0-2.95 0.37-5.9 1.09-8.76 51.31-201.82-70.7-407.02-272.52-458.33-29.89-7.6-60.59-11.5-91.43-11.62-19.68 0-35.64-15.95-35.64-35.63 0-19.68 15.95-35.64 35.63-35.64h0.01c247.57 0.76 447.65 202.08 446.89 449.65-0.11 36.8-4.76 73.44-13.83 109.1-4 15.8-18.23 26.88-34.54 26.88z"
                fill="currentColor"
                p-id="1748"
              ></path>
            </svg>
          </div>
          <template #overlay>
            <a-menu @click="handleLangMenuClick">
              <a-menu-item key="zh-CN">中文</a-menu-item>
              <a-menu-item key="en-US">English</a-menu-item>
              <a-menu-item key="ja-JP">日本語</a-menu-item>
            </a-menu>
          </template>
        </a-dropdown>
      </div>
    </div>

    <!-- 文件传输区域 -->
    <div class="file-transfer" :class="{ 'mobile-layout': isPhone }">
      <!-- 本地文件区域 -->
      <FileView
        v-if="!isPhone"
        :isRemote="false"
        :selectedFiles="selectedLocalFiles"
      />

      <!-- 传输控制 -->
      <div
        v-if="!isPhone"
        class="transfer-controls"
        :class="{ 'mobile-controls': isPhone }"
      >
        <Clipboard v-if="isConnected" />
        <Button
          type="primary"
          :disabled="!isConnected || selectedLocalFiles.length === 0"
          @click="handleSend"
        >
          {{ $t("index.send") }}
        </Button>
        <Button
          type="primary"
          :disabled="!isConnected || selectedRemoteFiles.length === 0"
          @click="handleReceive"
          :loading="receiveLoading"
        >
          {{ $t("index.receive") }}
        </Button>
      </div>

      <!-- 远程文件区域 -->
      <FileView :isRemote="true" :selectedFiles="selectedRemoteFiles" />
    </div>
  </div>
  <div class="author-footer">
    <a href="https://kuraa.cc" target="_blank" rel="noopener">{{
      $t("index.kuraaFooter")
    }}</a>
  </div>
  <FileTransferView />
</template>

<script setup lang="ts">
import Clipboard from "./item/clipboard.vue";
import { ref, onMounted } from "vue";
import { useI18n } from "vue-i18n";
import { peer } from "./utils/peer";
import FileView from "./item/fileView.vue";
import { notification } from "ant-design-vue";
import { fileMgrInstance, type FileData } from "./utils/fileMgr";
import { Button } from "ant-design-vue";
import DesktopView from "./item/desptopView.vue";
import {
  formatSize,
  getUrlParam,
  localCurrentFile,
  remoteCurrentFile,
  sign2peerid,
} from "./utils/common";
import FileTransferView from "./item/fileTranserView.vue";

const { locale, t } = useI18n();

const handleLangMenuClick = ({ key }: { key: string }) => {
  locale.value = key;
  const url = new URL(window.location.href);
  url.searchParams.set("lang", key);
  window.history.replaceState({}, "", url.href);
};

const isPhone = ref(false);
const receiveLoading = ref(false);
const myId = ref("");
const targetId = ref("");
const connectedPeerId = ref("");
const connectedPeerLabel = ref("");
const connectedPeerSign = ref("");
const isInboundConnected = ref(false);
const isConnected = ref(false);
const isConnecting = ref(false);
const isDesktopActive = ref(false);
const isCallActive = ref(false);
const isCameraActive = ref(false);
// 文件系统相关
const selectedLocalFiles = ref<string[]>([]);
const selectedRemoteFiles = ref<string[]>([]);
//根据文档宽度
onMounted(() => {
  isPhone.value = document.body.clientWidth < 768;
});

const requestDesktop = () => {
  if (!isConnected.value) return;
  if (isDesktopActive.value) {
    peer.endMedia(sign2peerid(targetId.value), "desktop");
    return;
  }
  peer.requestDesktop(targetId.value);
};
const requestCall = () => {
  if (!isConnected.value) return;
  if (isCallActive.value) {
    peer.endMedia(sign2peerid(targetId.value), "call");
    return;
  }
  peer.requestCall(targetId.value);
};
const requestCamera = () => {
  if (!isConnected.value) return;
  if (isCameraActive.value) {
    peer.endMedia(sign2peerid(targetId.value), "camera");
    return;
  }
  peer.requestCamera(targetId.value);
};

const shareUrl = async () => {
  if (myId.value) {
    const url =
      window.location.origin +
      window.location.pathname +
      "?sign=" +
      myId.value +
      "&lang=" +
      locale.value;
    await copyToClipboard(url);
    notification.success({
      message: t("index.linkCopied"),
      description: t("index.linkCopiedDesc"),
    });
  }
};

// 复制ID
const copyId = async () => {
  if (myId.value) {
    try {
      await copyToClipboard(myId.value);
      notification.success({
        message: t("index.idCopied"),
        description: t("index.idCopiedDesc"),
      });
    } catch (error) {
      notification.error({
        message: t("index.copyFailed"),
        icon: "error",
      });
    }
  }
};

const copyPeerSign = async () => {
  if (connectedPeerSign.value) {
    try {
      await copyToClipboard(connectedPeerSign.value);
      notification.success({
        message: t("index.idCopied"),
        description: t("index.idCopiedConnectDesc"),
      });
    } catch {
      notification.error({ message: t("index.copyFailed") });
    }
  }
};
//复制到剪贴板
const copyToClipboard = async (text: string) => {
  await navigator.clipboard.writeText(text);
};

// 连接处理
const handleConnect = () => {
  if (!targetId.value) return;
  isConnecting.value = true;
  peer.connect(targetId.value);
};

const updateConnectedPeer = (peerId: string, inbound: boolean) => {
  connectedPeerId.value = peerId;
  connectedPeerLabel.value = inbound
    ? `${peerId.slice(0, 8)}...`
    : targetId.value;
  isInboundConnected.value = inbound;
  isConnected.value = !inbound;
  isConnecting.value = false;
};

const clearConnectedPeer = (peerId?: string) => {
  if (peerId && connectedPeerId.value && connectedPeerId.value !== peerId)
    return;
  connectedPeerId.value = "";
  connectedPeerLabel.value = "";
  connectedPeerSign.value = "";
  isInboundConnected.value = false;
  isConnected.value = false;
  isConnecting.value = false;
};

const isActivePeer = (peerId: string) => {
  const targetPeerId = targetId.value ? sign2peerid(targetId.value) : "";
  return peerId === connectedPeerId.value || peerId === targetPeerId;
};
let lastBytes = 0;
let lastPackets = 0;
const transInfo = ref({
  bytes: 0,
  packets: 0,
});
const checkBytes = () => {
  transInfo.value.bytes = peer.transbytesNum - lastBytes;
  transInfo.value.packets = peer.transpackNum - lastPackets;
  lastBytes = peer.transbytesNum;
  lastPackets = peer.transpackNum;
  setTimeout(() => {
    checkBytes();
  }, 1000);
};
const handleSend = async () => {
  notification.info({
    message: t("index.notCompleted"),
    description: t("index.inDevelopment"),
  });
};
const handleReceive = async () => {
  receiveLoading.value = true;
  const rootFile = await fileMgrInstance.getRootFile();
  console.log(localCurrentFile.value.path);
  try {
    let getFileHandles: Promise<FileData | FileData[]>[] = [];
    selectedRemoteFiles.value.forEach((filepath) => {
      getFileHandles.push(
        fileMgrInstance.remoteRootFile
          .getFileInfo(filepath)
          .getFile(
            false,
            localCurrentFile.value.path.replace(rootFile.path, ""),
            remoteCurrentFile.value.path,
          ),
      );
    });
    await Promise.all(getFileHandles);
  } catch (err) {
    notification.error({
      message: t("index.receiveFilesFailed"),
    });
  }
  receiveLoading.value = false;

  await localCurrentFile.value.loadLocalDirectory();
};
// 事件监听
onMounted(async () => {
  await peer.init();
  peer.on("open", ((event: CustomEvent) => {
    myId.value = event.detail;
    const sign = getUrlParam("sign");
    if (sign) {
      targetId.value = sign;
      handleConnect();
    }
  }) as EventListener);

  peer.on("connection-open", ((event: CustomEvent) => {
    if (event.detail.peer == peer.remoteConnection?.peer) {
      checkBytes();
      updateConnectedPeer(event.detail.peer, false);
      fileMgrInstance.remoteRootFile.loadLocalDirectory();
      notification.success({
        message: t("index.connectSuccess"),
      });
    } else {
      updateConnectedPeer(event.detail.peer, true);
      notification.success({
        message: t("index.newConnection"),
      });
    }
  }) as EventListener);

  peer.on("peer-disconnected", ((event: CustomEvent) => {
    clearConnectedPeer(event.detail.peer);
    isDesktopActive.value = false;
    isCallActive.value = false;
    isCameraActive.value = false;
    notification.error({
      message: event.detail.peer + t("index.disconnected"),
    });
  }) as EventListener);

  peer.on("exchange-sign", ((event: CustomEvent) => {
    if (event.detail.peerId === connectedPeerId.value) {
      connectedPeerSign.value = event.detail.sign;
      if (isInboundConnected.value) {
        connectedPeerLabel.value = event.detail.sign;
      }
    }
  }) as EventListener);

  peer.on("error", ((event: CustomEvent) => {
    isConnecting.value = false;
    notification.error({
      message: t("index.errorOccurred"),
    });
    console.error("连接错误:", event.detail);
  }) as EventListener);

  peer.on("stream", ((event: CustomEvent) => {
    if (!isActivePeer(event.detail.peerId)) return;
    if (event.detail.type === "desktop") {
      isDesktopActive.value = true;
    } else if (event.detail.type === "call") {
      isCallActive.value = true;
    } else if (event.detail.type === "camera") {
      isCameraActive.value = true;
    }
  }) as EventListener);

  peer.on("desktop-started", ((event: CustomEvent) => {
    if (isActivePeer(event.detail.peerId)) {
      isDesktopActive.value = true;
    }
  }) as EventListener);

  peer.on("call-started", ((event: CustomEvent) => {
    if (isActivePeer(event.detail.peerId)) {
      isCallActive.value = true;
    }
  }) as EventListener);

  peer.on("camera-started", ((event: CustomEvent) => {
    if (isActivePeer(event.detail.peerId)) {
      isCameraActive.value = true;
    }
  }) as EventListener);

  peer.on("media-ended", ((event: CustomEvent) => {
    if (!isActivePeer(event.detail.peerId)) return;
    if (event.detail.type === "desktop") {
      isDesktopActive.value = false;
    } else if (event.detail.type === "call") {
      isCallActive.value = false;
    } else if (event.detail.type === "camera") {
      isCameraActive.value = false;
    }
  }) as EventListener);
});
</script>

<style scoped>
.container {
  padding: 20px;
  display: flex;
  flex-direction: column;
  height: calc(100vh - 75px);
  gap: 20px;
}

.status-bar {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  padding: 10px;
  background: #f5f5f5;
  border-radius: 8px;
}

.peer-info {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.connection-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 10px;
  border: 1px solid #95de64;
  border-radius: 999px;
  background: #f6ffed;
  color: #389e0d;
  font-size: 12px;
  white-space: nowrap;
}

.connection-badge.inbound {
  border-color: #91caff;
  background: #e6f4ff;
  color: #0958d9;
}

.connected-peer {
  font-family: monospace;
}

.connect-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 30px;
  height: 30px;
  background: #dff1ff;
  border-radius: 8px;
  cursor: pointer;
  border: 1px solid #82c7fb;
}
.connect-item:hover {
  background: #cae5f9;
}
.connect-item.active {
  background: #b7eb8f;
  border-color: #52c41a;
}
.connect-item.active:hover {
  background: #95de64;
}
.connect-item.disabled {
  background: #f0f0f0;
  border-color: #d9d9d9;
  cursor: not-allowed;
  opacity: 0.55;
}
.connect-item.disabled:hover {
  background: #f0f0f0;
}
.connect-item.disabled img {
  filter: grayscale(1);
}

.connect-item img {
  width: 100%;
  height: 100%;
}

.connect-item svg {
  width: 35px;
  height: 35px;
  margin: auto;
  color: #1677ff;
}

.status-info {
  display: flex;
  align-items: center;
  gap: 12px;
}

.status-actions,
.connect-actions,
.connect-section {
  display: flex;
  align-items: center;
  gap: 10px;
}

.status-actions {
  margin-left: auto;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.connect-section {
  flex-wrap: wrap;
}

.connect-section input {
  min-width: 220px;
}

.lang-switcher {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border: 1px solid #d9e6f7;
  border-radius: 999px;
  background: #ffffff;
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
  cursor: pointer;
  color: #1677ff;
  transition:
    background 0.2s,
    border-color 0.2s;
}

.lang-switcher:hover {
  background: #f0f6ff;
  border-color: #91caff;
}

.lang-switcher-icon {
  width: 22px;
  height: 22px;
}

.file-transfer {
  display: flex;
  flex: 1;
  gap: 20px;
  min-height: 0;
}

.file-transfer.mobile-layout {
  flex-direction: column;
}

.file-panel {
  flex: 1;
  display: flex;
  flex-direction: column;
  border: 1px solid #ddd;
  border-radius: 8px;
  overflow: hidden;
}

.panel-header {
  padding: 10px;
  background: #f5f5f5;
  border-bottom: 1px solid #ddd;
}

.path-nav {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 5px;
}

.file-list {
  flex: 1;
  overflow-y: auto;
  padding: 10px;
}

.file-item {
  display: flex;
  align-items: center;
  padding: 8px;
  cursor: pointer;
  border-radius: 4px;
  gap: 10px;
}

.file-item:hover {
  background: #f5f5f5;
}

.file-item.selected {
  background: #e3f2fd;
}

.file-icon {
  font-size: 24px;
}

.file-info {
  flex: 1;
}

.file-name {
  font-weight: 500;
}

.file-meta {
  font-size: 12px;
  color: #666;
}

.panel-footer {
  padding: 10px;
  background: #f5f5f5;
  border-top: 1px solid #ddd;
  display: flex;
  gap: 10px;
}

.transfer-controls {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 10px;
}

.transfer-progress {
  padding: 10px;
  background: #f5f5f5;
  border-radius: 8px;
}

.progress-info {
  display: flex;
  justify-content: space-between;
  margin-bottom: 5px;
}

.progress-bar {
  height: 4px;
  background: #ddd;
  border-radius: 2px;
  overflow: hidden;
}

.progress-fill {
  height: 100%;
  background: #007aff;
  transition: width 0.3s ease;
}

input {
  padding: 8px 12px;
  border: 1px solid #ddd;
  border-radius: 4px;
}

input:disabled {
  background: #f5f5f5;
}

.id-text {
  font-weight: bold;
  color: #007aff;
}

.author-footer {
  position: fixed;
  right: 16px;
  bottom: 12px;
  z-index: 999;
  line-height: 1;
}

.author-footer a {
  color: #bbb;
  font-size: 12px;
  text-decoration: none;
  transition: color 0.2s;
}

.author-footer a:hover {
  color: #007aff;
}

/* 移动端适配样式 */
@media screen and (max-width: 768px) {
  .status-bar {
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
  }

  .peer-info,
  .status-info,
  .status-actions,
  .connect-section {
    width: 100%;
  }

  .status-actions {
    margin-left: 0;
    justify-content: space-between;
  }

  .connect-section input {
    flex: 1;
    min-width: 0;
  }

  .status-info {
    justify-content: space-around;
  }

  .lang-switcher {
    margin-left: auto;
  }
}
</style>
