<template>
  <div class="trtccom" v-if="show">
    <Device @switchDevice="switchDevice" @canUseDevice="canUseDevice" />
    <div class="local" :class="{ disabledlocal: role == 'customer' || !videoDeviceId }" id="local" v-if="isJoined">
      <div class="micBox">
        <img v-if="muteAudioLeader" :src="require('@/assets/images/rtcLive/mic_off@2x.png')" alt="" />
        <i v-else class="speak_mic"></i>
      </div>
    </div>

    <template v-if="isJoined && invitedRemoteStreams.length > 0">
      <div
        class="local"
        :data-role="item.userId_"
        :class="{ disabledlocal: item.userId_.indexOf('customer') > -1 || !videoDeviceId }"
        v-for="item in invitedRemoteStreams"
        :id="item.userId_"
        :key="item.userId_"
      >
        <div class="micBox">
          <img v-if="muteAudioLeader" :src="require('@/assets/images/rtcLive/mic_off@2x.png')" alt="" />
          <i v-else class="speak_mic"></i>
        </div>
      </div>
    </template>

    <div class="videoBox userVideo" v-show="props.videoMuted || muteVideoLeader">
      <img :src="require('@/assets/images/rtcLive/avatar_small@2x.png')" alt="" />
      <div class="micBox">
        <img v-if="muteAudioLeader" :src="require('@/assets/images/rtcLive/mic_off@2x.png')" alt="" />
        <i v-else class="speak_mic"></i>
      </div>
    </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, onUnmounted } from "vue";
import Device from "./trtc/Device";
import { useStore } from "vuex";
import browser from "@/utils/browser";
// import * as apis from "@/apis/index.js";

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

const store = useStore();

const show = ref(false);
const invitedRemoteStreams = ref([]);

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

const muteAudioLeader = ref(false);
const muteVideoLeader = ref(false);

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

const initParamsStates = computed(
  () => !!(store.getters["rtc/sdkAppId"] && store.getters["rtc/secretKey"] && store.getters["rtc/roomId"] && store.getters["rtc/userId"])
);
const userSig = computed(() => store.getters["rtc/userSig"]);
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();
    }
    if (role.value == "leader") {
      muteAudioLeader.value = props.audioMuted;
    }
  }
);

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

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

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

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

    await localStream.initialize();
    if (props.audioMuted) {
      localStream.muteAudio();
      if (role.value == "leader") {
        muteAudioLeader.value = props.audioMuted;
      }
    }
  } catch (error) {
    console.log(error, "createStream");
  }
}

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

  try {
    // let res = await apis.getSign({ userId: store.getters["rtc/userId"] });
    localClient = TRTC.createClient({
      mode: "rtc",
      sdkAppId: parseInt(store.getters["rtc/sdkAppId"], 10),
      userId: store.getters["rtc/userId"],
      userSig: userSig.value,
      useStringRoomId: true,
      enableAutoPlayDialog: false,
    });
    installEventHandlers();

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

  await createLocalStream();
  await handlePublish();
  localStream
    .play("local")
    .then(() => {
      // addLocalControlView();
    })
    .catch((e) => {
      console.log(stream);
    });

  localStream.on("error", (error) => {
    if (error.getCode() === 0x4043) {
      // 自动播放受限导致播放失败，此时引导用户点击页面。
      // 在点击事件的回调函数中，执行 stream.resume();
      Dialog.confirm({
        showCloseIcon: false,
        okText: "确定",
        content:
          "<span style='font-size: 16px; line-height: 1.5;'>在用户与网页产生交互（例如点击、触摸页面等）之前，网页将被禁止播放带有声音的媒体。点击恢复播放<span/>",
        title: "隱私條款：",
        single: true,
        func: (state) => {
          if (state == "ok") {
            localStream.resume();
          }
        },
      });
    }
  });
}

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

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

async function handleStartShare() {
  shareClient = new ShareClient({
    sdkAppId: parseInt(store.getters["rtc/sdkAppId"], 10),
    userId: `share${store.getters["rtc/userId"]}`,
    roomId: store.getters["rtc/roomId"],
    secretKey: store.getters["rtc/secretKey"],
    useStringRoomId: true,
  });
  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 handleUnpublish() {
  if (!isJoined.value) {
    return;
  }
  if (!isPublished.value) {
    return;
  }
  try {
    await localClient.unpublish(localStream);
    store.commit("rtc/setIsPublished", false);
  } catch (error) {
    console.error(error, "-----------handleUnpublish--------------");
  }
}

async function handleLeave() {
  if (isPublished.value) {
    await handleUnpublish();
  }
  try {
    uninstallEventHandlers();
    await localClient.leave();
    localClient.destroy();
    localClient = null;
    invitedRemoteStreams.value.forEach((item) => {
      item.stop();
    });
    invitedRemoteStreams.value = [];
    store.commit("rtc/setVideoDeviceId", "");
    store.commit("rtc/setAudioDeviceId", "");

    if (localStream) {
      localStream.stop();
      localStream.close();
      localStream = null;
      console.log("有执行到这里-------------");
    }
  } catch (error) {
    console.error(error, "-----------handleLeave--------------");
  }
}

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`);
  if (event.userId.indexOf("leader") > -1) {
    muteVideoLeader.value = true;
  }
}

function handleMuteAudio(event) {
  if (event.userId.indexOf("leader") > -1) {
    muteAudioLeader.value = true;
  }
  console.log(event, `[] mute audio`);
}

function handleUnmuteVideo(event) {
  console.log(`[${event.userId}] unmute video`);
  if (event.userId.indexOf("leader") > -1) {
    muteVideoLeader.value = false;
  }
}

function handleUnmuteAudio(event) {
  console.log(`[${event.userId}] unmute audio`);
  if (event.userId.indexOf("leader") > -1) {
    muteAudioLeader.value = false;
  }
}

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();

  console.log(remoteStream, "-------------remoteStream");

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

async function handleStreamSubscribed(event) {
  const remoteStream = event.stream;

  if (remoteStream.userId_ == store.getters["rtc/userId"]) {
    return;
  }
  console.info(remoteStream.userId_, store.getters["rtc/userId"], "handleStreamSubscribedhandleStreamSubscribed.value");

  if (!invitedRemoteStreams.value.some((item) => item.userId_ == remoteStream.userId_)) {
    invitedRemoteStreams.value.push(remoteStream);
  }

  console.log(invitedRemoteStreams.value, "invitedRemoteStreams.value");

  await nextTick();
  setTimeout(() => {
    console.log(remoteStream.userId_, "remoteStream.getId()");
    remoteStream
      .play(remoteStream.userId_)
      .then(() => {
        console.log(`RemoteStream play success`, 88888888888888888888);
      })
      .catch((error) => {
        console.log(`RemoteStream play failed:  error: ${error.message_}`);
      });
  }, 100);

  // 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) {}
  }
};

onUnmounted(() => {
  handleLeave();
});

let canUseDevice = () => {
  console.log("可用");
  handleJoin();
};
</script>

<style lang="scss" scoped>
.trtccom {
  .local {
    width: 70px;
    height: 70px;
    position: fixed;
    z-index: 9999;
    top: 20px;
    left: 20px;
    border-radius: 50%;
    overflow: hidden;
    background: url(~@/assets/images/rtcLive/avatar_small@2x.png) center center no-repeat;
  }
  .videoBox {
    width: 72px;
    height: 72px;
    top: 19px;
    left: 19px;
    position: fixed;
    z-index: 99999;
    border-radius: 50%;
    overflow: hidden;
    .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: 100%;
      height: 100%;
    }
  }
  .micBox {
    width: 100%;
    height: 16px;
    background: rgba(0, 0, 0, 0.3);
    position: absolute;
    left: 0;
    bottom: 0;
    z-index: 100;
    display: flex;
    align-items: center;
    justify-content: center;
    .speak_mic {
      display: block;
      background-size: 720px auto;
      width: 12px;
      height: 12px;
      background-image: url(~@/assets/images/rtcLive/speed.png);
      // width: 0.69rem;
      // height: 0.69rem;
      animation: myAnimation 3s steps(59) infinite;
    }
    > img {
      width: 12px;
    }
  }
  .disabledlocal {
    opacity: 0 !important;
    visibility: hidden !important;
  }
}

@keyframes myAnimation {
  0% {
    background-position: 0px 0px;
  }

  100% {
    background-position: -708px 0px;
  }
}
</style>
