/*
Copyright (C) 2024 3NSoft Inc.

This program is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/>.
*/

import { computed, defineAsyncComponent, inject, onBeforeUnmount, onMounted, ref } from 'vue';
import { storeToRefs } from 'pinia';
import { DIALOGS_KEY, DialogsPlugin, I18N_KEY, I18nPlugin, VUEBUS_KEY, VueBusPlugin, type VueEventBus } from '@v1nt1248/3nclient-lib/plugins';
import { useAppStore } from '@video/store/app';
import { Peer, useStreamsStore } from '@video/store/streams';
import type { PeerEvents } from '@video/services/events';

export interface DataChannelMsg {
  mic?: 'on' | 'off';
  camera?: 'on' | 'off';
  state?: 'disconnected';
}

export default function useCall() {
  const appStore = useAppStore();
  const { user } = storeToRefs(appStore);
  const streams = useStreamsStore();
  const { singlePeer: peer } = storeToRefs(streams);
  const $emitter = inject<VueBusPlugin<PeerEvents>>(VUEBUS_KEY)!.$emitter as VueEventBus<PeerEvents>;
  const { $tr } = inject<I18nPlugin>(I18N_KEY)!;
  const dialog = inject<DialogsPlugin>(DIALOGS_KEY)!;

  const ownVideoTag = ref<HTMLVideoElement>();
  const peerVideoTag = ref<HTMLVideoElement>();
  const isFullscreen = ref(false);

  const peerVideoMuted = computed(() => {
    return !peer.value.ui.isCamOn;
  });
  const peerAudioMuted = computed(() => {
    return !peer.value.ui.isMicOn;
  });

  function setupPeerVideo(peer: Peer) {
    if (peer.channel.vaStream) {
      peerVideoTag.value!.srcObject = peer.channel.vaStream;
    } else {
    }
  }

  function toggleMicStatus() {
    streams.setMicOn(!streams.isMicOn);
    // sendMessageViaDataChannel({ mic: streams.isMicOn ? 'on' : 'off' });
  }

  function toggleCamStatus() {
    streams.setCamOn(!streams.isCamOn);
    // sendMessageViaDataChannel({ camera: streams.isCamOn ? 'on' : 'off' });
  }

  async function endCall() {
    if (peerVideoTag.value?.srcObject) {
      peerVideoTag.value.srcObject = null;
    }
    await peer.value.channel.close();
    w3n.closeSelf();
  }

  async function endCallWhenPeerCloses() {
    if (peerVideoTag.value?.srcObject) {
      peerVideoTag.value.srcObject = null;
    }
    w3n.closeSelf();
  }

  function fullscreenchangeHandler() {
    isFullscreen.value = !!document.fullscreenElement;
  }

  async function toggleFullscreen() {
    if (document.fullscreenElement) {
      await document.exitFullscreen();
    } else {
      await document.documentElement.requestFullscreen();
    }
  }

  async function openScreenShareChoice() {
    const component = defineAsyncComponent(() => import('../dialogs/screen-share-choice-dialog.vue'));
    dialog.$openDialog({
      component,
      componentProps: {
        // dialogText: 'This is the place for any text, passed iva props',
      },
      dialogProps: {
        title: 'Choose windows to share',
        onConfirm: shareSelectedShareChoices
      },
    });
  }

  function shareSelectedShareChoices(data: any) {
    // XXX
    console.log(`choices data is`, data);
  }

  $emitter.on('stream:added', ({ peerAddr, streamId, streamType }) => {
    console.log(` ---- stream:added captured`, peerAddr, streamId, streamType);
    if (peer.value.peerAddr === peerAddr) {
      if (streamType === 'camera+mic') {
        peerVideoTag.value!.srcObject = peer.value.channel.vaStream!;
      }
    }
  });

  $emitter.on('stream:removed', ({ peerAddr, streamId }) => {
    if (peer.value.peerAddr === peerAddr) {
      const stream = peer.value.channel.getStream(streamId);
      if (!stream) {
        return;
      }
      const sInfo = peer.value.ui.streams.find(s => (s.streamId === streamId));
      if (sInfo?.type === 'camera+mic') {
        peerVideoTag.value!.srcObject = null;
      }
    }

  });

  $emitter.on('peer:disconnected', ({ peerAddr }) => {
    if (peer.value.peerAddr === peerAddr) {
      peerVideoTag.value!.srcObject = null;
      endCallWhenPeerCloses();
    }
  });

  onMounted(() => {
    ownVideoTag.value!.srcObject = streams.ownVAStream;
    setupPeerVideo(peer.value);

    document.addEventListener('fullscreenchange', fullscreenchangeHandler);
  });

  onBeforeUnmount(() => {
    document.removeEventListener('fullscreenchange', fullscreenchangeHandler);
  });

  return {
    user,
    ownVideoTag,
    peerVideoTag,
    isFullscreen,
    streams,
    peerVideoMuted,
    peerAudioMuted,
    toggleMicStatus,
    toggleCamStatus,
    endCall,
    toggleFullscreen,
    openScreenShareChoice,
  };
}
