<template>
  <div class="trtccom" v-if="show">
    <Device @switchDevice="switchDevice" @canUseDevice="canUseDevice" />
    <div class="local" id="local" v-if="isJoined && role == 'leader'"></div>
    <div class="local" :id="clientId" v-if="isJoined && role == 'customer' && clientId"></div>
    <div class="videoBox userVideo" v-show="props.videoMuted">
      <img :src="require('@/assets/images/rtcLive/avatar_small@2x.png')" alt="" />
      <img class="loadingTip" :src="require('@/assets/images/rtcLive/loading@2x.png')" alt="" />
    </div>
  </div>
</template>

<script setup>
import TRTC, { Client, LocalStream } from "trtc-js-sdk";
import { Dialog } from "@/global_components/";
import { ref, computed, watch, defineEmits, defineProps, nextTick } from "vue";
import Device from "./trtc/Device";
import { useStore } from "vuex";
import browser from "@/utils/browser";

const emit = defineEmits(["audioMuted", "videoMuted"]);

const store = useStore();

const show = ref(false);
const clientId = ref("");

const role = ref(browser.getURLParam("role"));

const isJoined = computed(() => store.getters["rtc/isJoined"]);
const isPublished = computed(() => store.getters["rtc/isPublished"]);
const userSig = computed(() => store.getters["rtc/userSig"]);

const initParamsStates = computed(
  () => !!(store.getters["rtc/sdkAppId"] && store.getters["rtc/secretKey"] && store.getters["rtc/roomId"] && store.getters["rtc/userId"])
);

let localClient = "";
let localStream = "";
let shareClient = "";

const props = defineProps({
  audioMuted: {
    default: false,
  },
  videoMuted: {
    default: false,
  },
});

watch(
  () => props.audioMuted,
  () => {
    if (props.audioMuted) {
      localStream.muteAudio();
    } else {
      localStream.unmuteAudio();
    }
  }
);

watch(
  () => props.videoMuted,
  () => {
    if (props.videoMuted) {
      localStream.muteVideo();
    } else {
      localStream.unmuteVideo();
    }
  }
);


watch(
  () => isJoined.value,
  () => {
    if (!isJoined.value) {
      handleLeave()
    }
  }
);

TRTC.checkSystemRequirements().then((checkResult) => {
  console.log(checkResult.result, "checkResult.result");
  if (!checkResult.result) {
    Dialog.toast({ content: `您的設備不支持音視頻通訊`, type: "error" });
  } else {
    show.value = true;
  }
});

async function createLocalStream(video = true) {
  try {
    localStream = TRTC.createStream({
      userId: store.getters["rtc/userId"],
      audio: true,
      video: video,
      cameraId: store.getters["rtc/videoDeviceId"],
      microphoneId: store.getters["rtc/audioDeviceId"],
    });
    localStream.setVideoProfile("480p");

    await localStream.initialize();

    localStream
      .play("local")
      .then(() => {
        // addLocalControlView();
      })
      .catch((e) => {});
  } catch (error) {}
}

async function handleJoin() {
  console.log(!initParamsStates.value);
  if (!initParamsStates.value) {
    return;
  }

  try {
    localClient = TRTC.createClient({
      mode: "rtc",
      sdkAppId: parseInt(store.getters["rtc/sdkAppId"], 10),
      userId: store.getters["rtc/userId"],
      userSig: userSig.value,
    });
    installEventHandlers();

    await localClient.join({ roomId: parseInt(store.getters["rtc/roomId"], 10) });
    store.commit("rtc/setIsJoined", true);
    // inviteLink.value = store.commit("rtc/createShareLink");
  } catch (error) {
    console.error(error, "error-----------");
  }

  await createLocalStream();
  await handlePublish();

  localClient.on("stream-added", (event) => {
    const remoteStream = event.stream;
    // //订阅远端流
    localClient.subscribe(remoteStream);
  });
}

async function handlePublish() {
  if (!isJoined.value) {
    return;
  }
  if (isPublished.value) {
    return;
  }

  try {
    await localClient.publish(localStream);
    store.commit("rtc/setIsPublished", true);
  } catch (error) {}
}

async function handleStartShare() {
  shareClient = new ShareClient({
    sdkAppId: parseInt(store.getters["rtc/sdkAppId"], 10),
    userId: `share${store.getters["rtc/userId"]}`,
    roomId: parseInt(store.getters["rtc/roomId"], 10),
    secretKey: store.getters["rtc/secretKey"],
  });
  try {
    await shareClient.join();
    await shareClient.publish();
    console.log("Start share screen success");
    store.isShared = true;
  } catch (error) {
    console.error(`Start share error: ${error.message_}`);
  }
}

async function handleClientJoin() {
  if (!initParamsStates.value) {
    return;
  }

  try {
    localClient = TRTC.createClient({
      mode: "rtc",
      sdkAppId: parseInt(store.getters["rtc/sdkAppId"], 10),
      userId: store.getters["rtc/userId"],
      userSig: userSig.value,
    });
    installEventHandlers();

    await localClient.join({ roomId: parseInt(store.getters["rtc/roomId"], 10) });

    store.commit("rtc/setIsJoined", true);
  } catch (error) {
    console.error(error, "error-----------");
  }

  await createLocalStream(false);
  await handlePublish();
}

async function handleSubscribed(event) {}

async function handleUnpublish() {
  if (!isJoined.value) {
    return;
  }
  if (!isPublished.value) {
    return;
  }
  try {
    await localClient.unpublish(localStream);
    store.commit("rtc/setIsPublished", false);
  } catch (error) {}
}

async function handleLeave() {
  if (isPublished.value) {
    await handleUnpublish();
  }
  try {
    uninstallEventHandlers();
    await localClient.leave();
    if (localStream) {
      localStream.stop();
      localStream.close();
      localStream = null;
    }
  } catch (error) {}
}

function installEventHandlers() {
  if (!localClient) {
    return;
  }
  localClient.on("error", handleError);
  localClient.on("client-banned", handleBanned);
  localClient.on("peer-join", handlePeerJoin);
  localClient.on("peer-leave", handlePeerLeave);
  localClient.on("stream-added", handleStreamAdded);
  localClient.on("stream-subscribed", handleStreamSubscribed);
  localClient.on("stream-removed", handleStreamRemoved);
  localClient.on("stream-updated", handleStreamUpdated);
  localClient.on("mute-video", handleMuteVideo);
  localClient.on("mute-audio", handleMuteAudio);
  localClient.on("unmute-video", handleUnmuteVideo);
  localClient.on("unmute-audio", handleUnmuteAudio);
}

function uninstallEventHandlers() {
  if (!localClient) {
    return;
  }
  localClient.off("error", handleError);
  localClient.off("error", handleError);
  localClient.off("client-banned", handleBanned);
  localClient.off("peer-join", handlePeerJoin);
  localClient.off("peer-leave", handlePeerLeave);
  localClient.off("stream-added", handleStreamAdded);
  localClient.off("stream-subscribed", handleStreamSubscribed);
  localClient.off("stream-removed", handleStreamRemoved);
  localClient.off("stream-updated", handleStreamUpdated);
  localClient.off("mute-video", handleMuteVideo);
  localClient.off("mute-audio", handleMuteAudio);
  localClient.off("unmute-video", handleUnmuteVideo);
  localClient.off("unmute-audio", handleUnmuteAudio);
}

function handleMuteVideo(event) {
  console.log(`[${event.userId}] mute video`);
}

function handleMuteAudio(event) {
  console.log(`[${event.userId}] mute audio`);
}

function handleUnmuteVideo(event) {
  console.log(`[${event.userId}] unmute video`);
}

function handleUnmuteAudio(event) {
  console.log(`[${event.userId}] unmute audio`);
}

function handleError(error) {
  console.log(`LocalClient error: ${error.message_}`);
}

function handleBanned(error) {
  console.log(`Client has been banned for ${error.message_}`);
}

function handlePeerJoin(event) {
  const { userId } = event;
  if (userId !== "local-screen") {
    console.log(`Peer Client [${userId}] joined`);
  }
}

function handlePeerLeave(event) {
  const { userId } = event;
  if (userId !== "local-screen") {
    console.log(`[${userId}] leave`);
  }
}

function handleStreamAdded(event) {
  const remoteStream = event.stream;
  const id = remoteStream.getId();
  const userId = remoteStream.getUserId();

  if (remoteStream.getUserId() === store.getters["rtc/userId"]) {
    // don't need to screen shared by us
    localClient.unsubscribe(remoteStream).catch((error) => {
      console.error(`unsubscribe failed: ${error.message_}`);
    });
  } else {
    console.log(`remote stream added: [${userId}] ID: ${id} type: ${remoteStream.getType()}`);
    localClient.subscribe(remoteStream).catch((error) => {
      console.error(`subscribe failed: ${error.message_}`);
    });
  }
}

async function handleStreamSubscribed(event) {
  if (role.value == "customer") {
    const remoteStream = event.stream;
    clientId.value = remoteStream.getId();
    await nextTick();
    remoteStream
      .play(clientId.value)
      .then(() => {
        console.log(`RemoteStream play success`,88888888888888888888);
      })
      .catch((error) => {
        console.log(`RemoteStream play failed:  error: ${error.message_}`);
      });
  }

  // const remoteStream = event.stream;
  // const userId = remoteStream.getUserId();
  // console.log(`RemoteStream subscribed: [${userId}]`);
}

function handleStreamRemoved(event) {
  const remoteStream = event.stream;
  const userId = remoteStream.getUserId();
  console.log(`RemoteStream removed: [${userId}]`);
}

function handleStreamUpdated(event) {
  const remoteStream = event.stream;
  const userId = remoteStream.getUserId();
  console.log(`RemoteStream updated: [${userId}] audio:${remoteStream.hasAudio()} video:${remoteStream.hasVideo()}`);
}

let switchDevice = async ({ videoId, audioId }) => {
  if (!isJoined.value) {
    return;
  }
  if (videoId) {
    try {
      await localStream.switchDevice("video", videoId);
    } catch (error) {}
  }
  if (audioId) {
    try {
      await localStream.switchDevice("audio", audioId);
    } catch (error) {}
  }
};

let canUseDevice = () => {
  console.log("可用");

  if (role.value == "leader") {
    handleJoin();
  } else {
    handleClientJoin();
  }
};
</script>

<style lang="scss" scoped>
.trtccom {
  .local {
    width: 70px;
    height: 70px;
    position: fixed;
    z-index: 9999;
    top: 0.69rem;
    left: 0.53rem;
    border-radius: 50%;
    overflow: hidden;
    background: url(~@/assets/images/rtcLive/avatar_small@2x.png) center center no-repeat;
  }
  .videoBox {
    width: 72px;
    height: 72px;
    top: 0.67rem;
    left: 0.52rem;
    position: fixed;
    z-index: 99999;
    .loadingTip {
      position: absolute;
      z-index: 101;
      left: 0;
      top: 0;
      bottom: 0;
      right: 0;
      animation: Rotate 1.5s infinite;
      @keyframes Rotate {
        0% {
          transform: rotate(0deg);
        }
        100% {
          transform: rotate(360deg);
        }
      }
    }
    > img {
      width: 1.94rem;
      height: 1.94rem;
    }
  }
}
</style>
