/*
 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 { webrtcCAP } from "./webrtc-cap.js";
import { WebRTCPeer } from "./webrtc-peer.js";
const state = {
    myStream: undefined,
    peers: undefined,
    groupChatId: undefined,
};
const selectId = (id) => {
    const elem = document.querySelector(`#${id}`);
    if (!elem) {
        throw new Error(`HTML element with id '${id}' is missing`);
    }
    return elem;
};
const selectAll = (cName) => document.querySelector(`.${cName}`);
async function initStateAndUI() {
    const cmd = await w3n.shell.getStartedCmd();
    if (!cmd) {
        alert(`Video component has no call info from command`);
        return w3n.closeSelf();
    }
    state.myStream = await startOwnVideo();
    if (cmd.cmd === 'start-new-call') {
        state.peers = cmd.params[0].peers;
        if (state.peers.length === 0) {
            alert(`No peers given in command's call info`);
            return w3n.closeSelf();
        }
        else if (state.peers.length > 1) {
            alert(`Group video chat is not implemented, yet`);
            return w3n.closeSelf();
        }
        selectId('start-call-btn').removeAttribute('hidden');
    }
    else {
        alert(`Handling of command '${cmd.cmd}' is not implemented, yet`);
        return w3n.closeSelf();
    }
}
async function startOwnVideo() {
    const stream = await navigator.mediaDevices.getUserMedia({
        audio: true,
        video: true
    });
    const display = selectId('selfview');
    display.srcObject = stream;
    return stream;
}
async function startCallTo(peer) {
    // XXX for a group chart, for each p2p link we should designate, who starts:
    //     - initiator of a group call is an initiator of all its p2p links,
    //     - in other p2p links, peer with a "smaller" lexigraphically canonical
    //       id will be starting that link
    // setup in a webrtc CAP should be done by chat component that
    // prepaires a non-webrtc message to start a call
    await webrtcCAP.addCallSignalingChannel(peer.address, peer.callRequestId, {
        msgType: 'chat',
        recipients: state.peers.map(({ address }) => address),
        jsonBody: {
        // XXX this needs to be chat service message with necessary details
        }
    });
    selectId('peer-name').textContent = peer.name;
    selectId('remoteview-container').removeAttribute('hidden');
    let remoteVideo = selectId('remoteview');
    if (!remoteVideo) {
        throw new Error(`Html video element not found`);
    }
    const { channel, rtcConfig, callStartedAt } = await webrtcCAP.getSignalingChannel(peer.address, peer.callRequestId);
    peer.rtcPeer = WebRTCPeer.makeWith(rtcConfig, channel, callStartedAt === 'local');
    peer.rtcPeer.ontrack = ({ track, streams }) => {
        track.onunmute = () => {
            // this assumes that both tracks arrive in the same stream which is
            // attached once
            if (remoteVideo) {
                remoteVideo.srcObject = streams[0];
                remoteVideo = undefined;
            }
        };
    };
    peer.rtcPeer.ondisconnected = clearStateAndNavigateToStart;
    peer.rtcPeer.sendMediaStream(state.myStream);
}
// async function acceptCallFrom(peer: PeerState): Promise<void> {
// 	// setup in a webrtc CAP should be done by chat component that
// 	// received non-webrtc message to start a call
// 	await webrtcCAP.addCallSignalingChannel(peerAddr, callId, 'remote');
// }
let peer;
async function startVideoCall() {
    selectId('selfview-container').classList.add('small-own-video');
    selectId('start-call-btn').setAttribute('hidden', '');
    selectId('end-call-btn').removeAttribute('hidden');
    await startCallTo(state.peers[0]);
}
async function endCall() {
    try {
        peer.close();
    }
    catch (err) {
        console.error(err);
    }
    clearStateAndNavigateToStart();
}
function clearStateAndNavigateToStart() {
    state.peers?.forEach(({ rtcPeer }) => rtcPeer?.close());
    w3n.closeSelf();
}
document.body.onload = initStateAndUI;
window.startVideoCall = startVideoCall;
window.endCall = endCall;
