<script setup>

import axios from '@axios';
import {
  LocalParticipant,
  Room,
  RoomEvent,
  Track,
  VideoPresets,
  facingModeFromLocalTrack
} from 'livekit-client';
import { defineEmits, defineProps, nextTick, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
const router = useRouter()
const route = useRoute()
const props = defineProps({
  token: {
    type: String,
    required: true,
  }, recording: {
    type: Boolean,
    default: false,
  },
  height: {
    type: String,
    required: false,
    default: ''
  }
})
const emit = defineEmits([
  'update:token',
  'update:transcriptData'
])
let room = null
const url = "wss://plugnmeet.codelfi.com"
const participants = ref([])
const cameras = ref([])
const cameraDefault = ref()
const microphones = ref([])
const microphoneDefault = ref()
const speakers = ref([])
const speakerDefault = ref()
const callStart = ref(false)
const userType = ref(localStorage.getItem('user_role'))
const recording = ref(false)
const isMobile = ref(window.innerWidth <= 768);
const transcriptData = ref('')
let rtCon = null
const appointmentId = localStorage.getItem('patient_appiontment_id')
const strData = JSON.stringify({ some: "data" })
const decoder = new TextDecoder()



const checkMobile = () => {
  isMobile.value = window.innerWidth <= 768; // Adjust the breakpoint as needed
};
onMounted(async () => {
  window.addEventListener('resize', checkMobile);
  document.addEventListener('mousemove', handleMouseMove)
  connect();
  // if (userType.value == 'agent')
  //   getAppointmentDetails();
});
onUnmounted(() => {
  window.removeEventListener('resize', checkMobile);
  document.removeEventListener('mousemove', handleMouseMove)

});


const x = ref(0)
const y = ref(0)
const dragging = ref(false)

const rect = ref(null)

const style = computed(() => {
  return {
    transform: `translate(${x.value}px, ${y.value}px)`
  }
})


const handleMouseDown = e => {
  rect.value = e.currentTarget.getBoundingClientRect()
  dragging.value = true
}

const handleMouseMove = e => {
  if (!dragging.value) return
  x.value = Math.min(Math.max(0, e.clientX - rect.value.left), window.innerWidth - rect.value.width) - 25
  y.value = Math.min(Math.max(0, e.clientY - rect.value.top), window.innerHeight - rect.value.height) - 25
}

const connect = async () => {

  room = new Room({
    // automatically manage subscribed video quality
    adaptiveStream: true,

    dynacast: true,

    // default capture settings
    videoCaptureDefaults: {
      resolution: VideoPresets.h720.resolution,
    },
  });

  // pre-warm connection, this can be called as early as your page is loaded
  room.prepareConnection(url, props.token);
  console.log(props.token)

  // set up event listeners
  room
    .on(RoomEvent.TrackSubscribed, (track, publication, participant) => renderParticipant(participant))
    .on(RoomEvent.TrackUnsubscribed, (track, publication, participant) => renderParticipant(participant, true))
    // .on(RoomEvent.ActiveSpeakersChanged, (speakers) => console.log("handleTrackSubscribed"))
    .on(RoomEvent.Disconnected, () => {
      renderParticipant(room.localParticipant, true)
      room.participants.forEach((p) => {
        renderParticipant(p, true);
      })
      room = null
    })
    .on(RoomEvent.Reconnecting, () => appendLog('Reconnecting to room'))
    .on(RoomEvent.Reconnected, async () => {
      appendLog(
        'Successfully reconnected. server',
        await room.engine.getConnectedServerAddress(),
      );
    })
    .on(RoomEvent.ParticipantConnected, async (participant) => {
      console.log('ParticipantConnected')
      callStart.value = true

    })
    .on(RoomEvent.DataReceived, async (payload, participant, kind) => {
      const strData = decoder.decode(payload)
      transcriptData.value = strData
      emit('update:transcriptData', transcriptData.value);
      console.log('strData', strData)
    })
    .on(RoomEvent.ParticipantDisconnected, (participant) => {
      renderParticipant(participant, true);
      console.log('part length ', room.participants.size)
      setTimeout(() => {
        if (room.participants.size == 0) {
          console.log('disconnect')
          room.disconnect();
          callStart.value = false

          // if (userType.value == 'agent')
          //   router.push('/queue-users');

          if (userType.value == 'patient') {
            localStorage.setItem('call-end-message', 'Password Sent to Email Address')
            router.push('/overview');
          }
        }

      }, 1000)



    })
    .on(RoomEvent.MediaDevicesChanged, async () => {
      console.log('device changed')
    })
    .on(RoomEvent.LocalTrackUnpublished, () => renderParticipant(room.localParticipant))
    .on(RoomEvent.LocalTrackPublished, () => renderParticipant(room.localParticipant));

  // connect to room
  await room.connect(url, props.token);
  console.log("connected to room", room.name);
  // publish local camera and mic tracks
  await room.localParticipant.enableCameraAndMicrophone();
  callStart.value = true
  // connectSpeach();

  if (props.recording == true) {

    await axios.post('/agent/api/start-record/' + localStorage.getItem('patient_appiontment_id'))
      .then(response => {
        console.log('start rec', response.data.message)
        if (response.data.message == 'Success')
          recording.value = response.data.message

      });

  }
  room.participants.forEach((participant) => {
    renderParticipant(participant);
  });
  renderParticipant(room.localParticipant);

  const videoDevices = await Room.getLocalDevices('videoinput');
  const audioDevices = await Room.getLocalDevices('audioinput');
  const audioOutputs = await Room.getLocalDevices('audiooutput');
  callStart.value = true
  let selectedVideoDevice = videoDevices[0];
  let selectedMicDevice = audioDevices[0];
  let selectedSpeakerDevice = audioOutputs[0];

  cameras.value = videoDevices;
  microphones.value = audioDevices;
  speakers.value = audioOutputs;

  console.log('camera ', cameras.value)
  console.log('mic ', microphones.value)
  console.log('speaker ', speakers.value)
  // console.log('Devices ',videoDevices,audioDevices,audioOutputs)
  if (videoDevices.length > 0) {
    for (const videoDevice of videoDevices) {

      if (videoDevice.deviceId == 'default') {
        selectedVideoDevice = videoDevice
        break;
      }
    }
    cameraDefault.value = selectedVideoDevice.deviceId
    console.log('default video', cameraDefault.value)
    await room.switchActiveDevice('videoinput', cameraDefault.value);
  }
  if (audioDevices.length > 0) {
    for (const audioDevice of audioDevices) {

      if (audioDevice.deviceId == 'default') {
        selectedMicDevice = audioDevice
        break;
      }
    }
    microphoneDefault.value = selectedMicDevice.deviceId
    console.log('default mic', microphoneDefault.value)
    await room.switchActiveDevice('audioinput', microphoneDefault.value);
  }
  if (audioOutputs.length > 0) {
    for (const audioOutput of audioOutputs) {

      if (audioOutput.deviceId == 'default') {
        selectedSpeakerDevice = audioOutput
        break;
      }
    }
    speakerDefault.value = selectedSpeakerDevice.deviceId
    console.log('default audio', speakerDefault.value)
    await room.switchActiveDevice('audiooutput', speakerDefault.value);
  }


  return room;
}

const renderParticipant = async (participant, remove = false) => {
  let _participant = participants.value.find(part => part.id == participant.identity)
  if (!_participant) {
    _participant = {
      id: participant.identity,
      type: (participant instanceof LocalParticipant) ? "local" : "remote",
      video: null,
      audio: null,
    };
    participants.value.push(_participant)

  }

  if (remove) {
    participants.value.splice(participants.value.indexOf(_participant), 1)
    return;
  }

  const cameraPub = participant.getTrack(Track.Source.Camera);
  const micPub = participant.getTrack(Track.Source.Microphone);

  await nextTick()
  // if ((participant instanceof LocalParticipant) && micPub?.track.getProcessor()?.name != "local-processor") {
  //   micPub.track.setProcessor(localProcessor);
  // }
  // if (micPub?.getProcessor()?.name != "remote-processor" && !(participant instanceof LocalParticipant)) {
  //   micPub.setProcessor(remoteProcessor);
  // }
  window.r = room
  _participant.video = document.getElementById("video-" + _participant.id)
  _participant.audio = document.getElementById("audio-" + _participant.id)
  console.log('video ', _participant.video)




  const cameraEnabled = cameraPub && cameraPub.isSubscribed && !cameraPub.isMuted;
  if (cameraEnabled) {

    cameraPub?.videoTrack?.attach(_participant.video);
  } else {
    if (cameraPub?.videoTrack) {
      // detach manually whenever possible
      cameraPub.videoTrack?.detach(_participant.video);
    } else if (_participant.video) {

      _participant.video.src = '';
      _participant.video.srcObject = null;
    }
  }


  const micEnabled = micPub && micPub.isSubscribed && !micPub.isMuted;
  if (micEnabled) {
    if (!(participant instanceof LocalParticipant)) {



      if (!rtCon) {
        micPub?.audioTrack?.attach(_participant.audio);

        console.log('audioTrack', _participant.audio)
      }
    }
  }




}

const endCall = async () => {
  room.disconnect()
  callStart.value = false

  if (userType.value == 'agent')
    router.push('/provider/queue-users');

  if (userType.value == 'patient') {
    localStorage.setItem('call-end-message', 'Password Sent to Email Address')
    router.push('/doctor-appiontments');
  }
}

const getAppointmentDetails = async () => {
  axios.post('/agent/api/appointment-detail/' + appointmentId)
    .then(r => {
      let appointmentAnalytics = r.data.agent_appointment.analytics
      transcriptData.value = appointmentAnalytics
      console.log('appointmentAnalytics ', transcriptData.value)
      emit('update:transcriptData', transcriptData.value);
    }).catch(error => {
      console.log("Error", error);
    });

}

const flipCamera = () => {
  const videoPub = room?.localParticipant.getTrack(Track, Source.Camera);
  if (!videoPub) {
    return;
  }
  const track = videoPub.track;
  const facingMode = track && facingModeFromLocalTrack(track);

  const options = {
    resolution: VideoPresets.h720.resolution,
    facingMode: facingMode?.facingMode === 'environment' ? 'user' : 'environment',
  }
  videoPub.videoTrack?.restartTrack(options)
}

const selectCamera = async (deviceId) => {
  await room.switchActiveDevice('videoinput', deviceId);
  cameraDefault.value = deviceId
  console.log('camera selected  ', deviceId);
}

const selectMicrophone = async (deviceId) => {
  await room.switchActiveDevice('audioinput', deviceId);
  microphoneDefault.value = deviceId
  console.log('mic selected  ', deviceId);
}

const selectSpeaker = async (deviceId) => {
  await room.switchActiveDevice('audiooutput', deviceId);
  speakerDefault.value = deviceId
  console.log('speaker selected  ', deviceId);
}



</script>


<template>
  <VCard class="text-center text-sm-start rounded-0">
    <div v-if="audioDevices">{{ audioDevices }}</div>
    <div class="livekit-container" @mouseup="dragging = false" @mouseleave="dragging = false"
      :style="`height:` + height">
      <div class="recording-badge" v-if="recording">Recording</div>
      <!-- <v-card class="draggable-card" width="150px" height="150px" color="light" @mousedown=""></v-card> -->

      <template v-for="(participant, index) in participants" :key="index" :value="index">
        <div v-if="participant.type == 'local'" :style="style" @mousedown="handleMouseDown" class="box">
          <video class="small-video" ref="participant.video" :id="`video-` + participant.id"></video>
          <audio ref="participant.audio" :id="`audio-` + participant.id"></audio>
        </div>
        <div class="remote-box" v-if="participant.type == 'remote'">
          <video class="large-video" ref="participant.video" :id="`video-` + participant.id"></video>
          <audio ref="participant.audio" :id="`audio-` + participant.id"></audio>
        </div>
      </template>
    </div>
    <VRow style="background-color: black;" v-if="callStart">
      <VCol cols="12" md="12">
        <div class="text-center mb-2">

          <v-btn-toggle v-if="!isMobile" v-model="toggle" divided rounded="xl">
            <v-row no-gutters>
              <v-btn class="btn btn-secondary waves-effect waves-light" color="white" icon="mdi-microphone"
                style="background-color: white;color: black;"></v-btn>

              <v-menu :location="top">
                <template v-slot:activator="{ props }">
                  <v-btn color="white" v-bind="props" icon="mdi-chevron-up" title="Devices">
                  </v-btn>
                </template>
                <v-list>
                  <v-list-item>
                    <v-list-item-title>

                      <v-menu :location="top">
                        <template v-slot:activator="{ props }">
                          <v-btn color="white" v-bind="props">Camera
                            <VIcon icon="mdi-chevron-up"></VIcon>
                          </v-btn>
                        </template>
                        <v-list>
                          <v-list-item v-for="(camera, index) in cameras" :key="index" :value="camera.deviceId"
                            @click="selectCamera(camera.deviceId)">
                            <v-list-item-title>
                              <VIcon color="green" icon="mdi-check" v-if="cameraDefault == camera.deviceId"></VIcon>
                              {{ camera.label }}
                            </v-list-item-title>
                          </v-list-item>
                        </v-list>
                      </v-menu>
                    </v-list-item-title>
                    <v-list-item-title>

                      <v-menu :location="top">
                        <template v-slot:activator="{ props }">
                          <v-btn color="white" v-bind="props">Microphone
                            <VIcon icon="mdi-chevron-up"></VIcon>
                          </v-btn>
                        </template>
                        <v-list>
                          <v-list-item v-for="(microphone, index) in microphones" :key="index"
                            :value="microphone.deviceId" @click="selectMicrophone(microphone.deviceId)">
                            <v-list-item-title>
                              <VIcon color="green" icon="mdi-check" v-if="microphoneDefault == microphone.deviceId">
                              </VIcon>
                              {{ microphone.label }}
                            </v-list-item-title>
                          </v-list-item>
                        </v-list>
                      </v-menu>
                    </v-list-item-title>
                    <v-list-item-title>

                      <v-menu :location="top">
                        <template v-slot:activator="{ props }">
                          <v-btn color="white" v-bind="props">Speaker
                            <VIcon icon="mdi-chevron-up"></VIcon>
                          </v-btn>
                        </template>
                        <v-list>
                          <v-list-item v-for="(speaker, index) in speakers" :key="index" :value="speaker.deviceId"
                            @click="selectSpeaker(speaker.deviceId)">
                            <v-list-item-title>
                              <VIcon color="green" icon="mdi-check" v-if="speakerDefault == speaker.deviceId"></VIcon>
                              {{ speaker.label }}
                            </v-list-item-title>
                          </v-list-item>
                        </v-list>
                      </v-menu>
                    </v-list-item-title>
                  </v-list-item>
                </v-list>
              </v-menu>
              <v-btn class="btn btn-secondary waves-effect waves-light" color="white" icon="mdi-video"
                style="background-color: white;color: black;"></v-btn>
            </v-row>
          </v-btn-toggle>

          <v-btn v-if="isMobile" class="btn btn-secondary waves-effect waves-light" color="white" icon="mdi-camera-flip"
            style="background-color: white;color: black;" @clicK="flipCamera"></v-btn>

          <v-btn rounded="xl" class="btn btn-danger waves-effect waves-light ml-2" color="red" icon="mdi-phone-hangup"
            @click="endCall()"></v-btn>
        </div>
      </VCol>
    </VRow>
    <!-- <div id="jaas-container" >
        </div> -->
    <!-- Show the iframe when countdown reaches 1 -->
    <!-- <iframe v-if="showIframe" ref="myIframe" :src="responseUrl" width="100%" height="400" style="border:0"></iframe>
        <div v-else>
          Loading iframe...
        </div> -->
  </VCard>
</template>
<style scoped>
.recording-badge {
  text-align: right;
  color: white;
  margin-right: 10px;
  background: red;
  min-width: 10%;
  float: right;
  border-radius: 25px;
  padding-right: 3px;
  z-index: 10;
  position: relative;
}

.small-screen {
  background-color: white;
  min-height: 150px;
  max-width: 24%;
}

.livekit-container {
  min-height: 500px;
  background-color: black;
  position: relative;
}

.draggable-card {
  cursor: move;
  position: relative;
}

.box {
  position: absolute;
  cursor: move;
  width: 150px;
  height: 150px;
  background: #313131;
  border-radius: 10px;
  margin-left: 10px;
  z-index: 2;
}

.large-video {
  height: 100%;
  width: 100%;
}

.small-video {
  max-width: 100%;
  height: 100%;
  max-height: 100%;
  width: auto;
  z-index: 9;
}

.remote-box {
  position: absolute;
  z-index: 1;
  width: 100%;
  height: 100%;
}
</style>
