/*
Copyright (C) 2024 - 2025 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 { useStreamsStore } from '@video/store/streams';
import type { PeerEvents } from '@video/services/events';
import { SharedStream } from '@video/components/types';

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 isFullscreen = ref(false);

  const peerVideoMuted = computed(() => !peer.value.isCamOn);
  const peerAudioMuted = computed(() => !peer.value.isMicOn);
  const peerVA = computed(
    () => streams.getStreams(peer.value.peerAddr, 'camera+mic')![0]
  );
  const peerSharedStreams = computed(() => [
    ...streams.getStreams(peer.value.peerAddr, 'screen'),
    ...streams.getStreams(peer.value.peerAddr, 'window')
  ]);

  function toggleMicStatus() {
    streams.setMicOn(!streams.isMicOn);
  }

  function toggleCamStatus() {
    streams.setCamOn(!streams.isCamOn);
  }

  async function endCall() {
    await peer.value.channel.close();
    w3n.closeSelf();
  }

  async function endCallWhenPeerCloses() {
    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',
        intiallyShared: (streams.ownScreens ? streams.ownScreens.concat() : [])
      },
      dialogProps: {
        title: 'Choose windows to share',
        onConfirm: shareSelectedShareChoices
      },
    });
  }

  function shareSelectedShareChoices(selected: SharedStream[]|null) {
    if (!selected) {
      return;
    }
    // unshare those not among selected
    streams.ownScreens
    ?.filter(({ srcId }) => !selected.find(s => (s.srcId === srcId)))
    .forEach(({ srcId }) => streams.removeOwnScreen(srcId));
    // add selected if not already shared
    for (const { srcId, stream, type } of selected) {
      if (!streams.ownScreens?.find(s => (s.srcId === srcId))) {
        streams.addOwnScreen(stream, type, srcId);
      }
    }
  }

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

  onMounted(() => {
    document.addEventListener('fullscreenchange', fullscreenchangeHandler);
  });

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

  return {
    user,
    isFullscreen,
    streams,
    peerVA,
    peerName: streams.singlePeer.peerName,
    peerSharedStreams,
    peerVideoMuted,
    peerAudioMuted,
    toggleMicStatus,
    toggleCamStatus,
    endCall,
    toggleFullscreen,
    openScreenShareChoice,
  };
}
