/**
 * Speed of pan and tilt
 * @type {number} 0 - 3F (hex) / 63 (dec)
 */
let pan_speed = 20;
let tilt_speed = 20;
let video_quality = "LQ";
/**
 * @type {WebSocket}
 */
let ws;

let camerastream;

// socketio
let socketio;

let files = [null,null,null,null,null];

let getbase64handle;
let getsysteminfohandle;

let $zoom;
let $mute;
let $unmute;

window.addEventListener("unload",function (){
    clearInterval(getbase64handle);
    clearInterval(getsysteminfohandle);
    send_stop_audio();
    // wait a while
    const start = Date.now();
    while(Date.now()-start<200){}
    ws.close();

})

window.addEventListener("load", function (){
    $zoom = $('#zoom');
    $mute = $('#mute');
    $unmute = $('#unmute');

    camerastream = document.getElementById("camerastream");

    // pilihan komunikasi, disable salah satu
    initialize_socketio();
    //initialize_websocket();

    // Update camera stream every 50ms  / 20fps
    getbase64handle = setInterval(function (){
        send_get_base64();
    },1000/15);

    getsysteminfohandle = setInterval(function (){
        send_get_system_info();
    }, 5000);
    set_pan_speed(32);
    set_tilt_speed(32);
})

function initialize_socketio(){
    socketio = io(":3001/socketio");
    if (socketio){
        socketio.on("connect",()=>{
            console.log("Socket.io Connected to the server");
            send_get_max_zoom();
            send_get_volume();
            send_get_zoom();
            send_get_resolution();
            send_get_audiofiles();
        })
        socketio.on("disconnect",(reason)=>{
            console.log("Socket.io Disconnected from server because "+reason);
        })
        socketio.on("connect_error",(error)=>{
            console.log("Socket.io Connection error "+error);
        });


        socketio.on("message",(data)=>{
            let dx = JSON.parse(data);
            process_command(dx);
        });
    }
}

function initialize_websocket(){
    ws = new WebSocket("/ws");
    if (ws){
        ws.onopen = function(){
            console.log("Connected to the server");

            // request basic parameters
            send_get_max_zoom();
            send_get_volume();
            send_get_zoom();
            send_get_resolution();
            send_get_audiofiles();

        }
        ws.onmessage = function(event){
            //console.log("Received data from server: " + event.data);
            /**
             * @type {{reply: string, data: string|number, additional: string}} dx
             */
            let dx = JSON.parse(event.data);
            process_command(dx);
        }
        ws.onclose = function(){
            console.log("Connection closed");
        }
        ws.onerror = function(){
            console.log("Error in connection");
        }
    }

}



/**
 * Update camera stream
 * @param {String} value
 */
function update_camerastream(value){
    if (camerastream){
        if (value && value.length>0){
            camerastream.src = value;
        } else {
            if (camerastream.src!== "public/images/not-available.png") camerastream.src = "public/images/not-available.png";
        }
    }

}


/**
 * Disable play button
 * @param index 1 - 5
 */
function play_off(index){
    $('#div'+index).prop("className", "button-container div-disabled");
    $('#btn_play'+index)
        .prop("className", "btn-play1 show text-light");
}

/**
 * Enable play button
 * @param index 1 - 5
 */
function play_on(index){
    let content = $('#desc_content'+index).html();
    $('#div'+index).prop("className", "button-container");
    $('#btn_play'+index)
        .prop("className", "btn-play1 show")
        .prop("title","Play "+content);
    $('#btn_stop'+index)
        .prop("title","Stop "+content);
}

/**
 * Show play button and hide stop button
 * @param index 1 - 5
 */
function show_play_and_hide_stop(index){
    $('#btn_play'+index).prop("className", "btn-play1 show");
    $('#btn_stop'+index).prop("className", "btn-play1 hide");
}

/**
 * Show stop button and hide play button
 * @param index 1 - 5
 */
function show_stop_and_hide_play(index){
    $('#btn_play'+index).prop("className", "btn-play1 hide");
    $('#btn_stop'+index).prop("className", "btn-play1 show");

}

/**
 * Enable all play buttons
 */
function allplay(){
    for (let i = 0; i < 5; i++) {
        if (files[i]) play_on(i+1);
    }
}

/**
 * When play button is clicked
 * @param index 1 - 5
 */
function play_button(index){
    show_stop_and_hide_play(index);
    $('#status_player').html("Play");
    for (let i = 1; i <= 5; i++){
        if (i!==index) play_off(i);
    }
    send_play_audio(index);
}

/**
 * When stop button is clicked
 * @param index 1 - 5
 */
function stop_button(index){
    show_play_and_hide_stop(index);
    $('#status_player').html("Stop");
    allplay();
    send_stop_audio();
}

function send_get_audiofiles(){
    let cmd = JSON.stringify({
        command: "GET AUDIOFILES",
        data: 0
    });
    if (ws){
        if (ws.readyState===WebSocket.OPEN){
            ws.send(cmd)
        } else console.log("WebSocket is not open");
    } else if (socketio){
        if (socketio.connected){
            socketio.emit("message",cmd);
        } else console.log("Socket.io is not connected");
    }

}

function send_get_resolution(){
    let cmd = JSON.stringify({
        command: "GET RESOLUTION",
        data: 0
    });
    if (ws){
        if (ws.readyState === WebSocket.OPEN){
            ws.send(cmd);
        } else console.log("WebSocket is not open");
    } else if (socketio){
        if (socketio.connected){
            socketio.emit("message",cmd);
        } else console.log("Socket.io is not connected");
    }

}

function send_get_zoom(){
    let cmd = JSON.stringify({
        command: "GET ZOOM",
        data: 0
    });
    if (ws){
        if (ws.readyState===WebSocket.OPEN){
            ws.send(cmd);
        } else console.log("WebSocket is not open");
    } else if (socketio){
        if (socketio.connected){
            socketio.emit("message",cmd);
        } else console.log("Socket.io is not connected");
    }


}

function send_get_volume(){
    let cmd = JSON.stringify({
        command: "GET VOLUME",
        data: 0
    });
    if (ws){
        if (ws.readyState === WebSocket.OPEN){
            ws.send(cmd);
        } else console.log("WebSocket is not open");
    } else if (socketio){
        if (socketio.connected){
            socketio.emit("message",cmd);
        } else console.log("Socket.io is not connected");
    }

}

function send_get_max_zoom(){
    let cmd = JSON.stringify({
        command: "GET MAX ZOOM",
        data: 0
    });
    if (ws){
        if (ws && ws.readyState===WebSocket.OPEN){
            ws.send(cmd);
        } else console.log("WebSocket is not open");
    } else if (socketio){
        if (socketio.connected){
            socketio.emit("message",cmd);
        } else console.log("Socket.io is not connected");
    }

}

function send_get_system_info(){
    let cmd = JSON.stringify({
        command: "GET SYSTEM INFO",
        data: 0
    });
    if (ws){
        if (ws.readyState === WebSocket.OPEN){
            ws.send(cmd);
        } else console.log("WebSocket is not open");
    } else if (socketio){
        if (socketio.connected){
            socketio.emit("message",cmd);
        } else console.log("Socket.io is not connected");
    }

}

/**
 * Send command to stop audio
 */
function send_stop_audio(){
    let cmd = JSON.stringify({
        command: "STOP AUDIO",
        data: 0
    });
    if (ws){
        if (ws.readyState === WebSocket.OPEN){
            ws.send(cmd);
        } else console.log("WebSocket is not open");
    } else if (socketio){
        if (socketio.connected){
            socketio.emit("message",cmd);
        } else console.log("Socket.io is not connected");
    }

}

function send_get_base64(){
    let cmd = JSON.stringify({
        command: "GET BASE64",
        data: video_quality
    });
    if (ws){
        if (ws.readyState === WebSocket.OPEN){
            ws.send(cmd);
            return;
        } else console.log("WebSocket is not open");
    } else if (socketio){
        if (socketio.connected){
            socketio.emit("message",cmd);
            return;
        } else console.log("Socket.io is not connected");
    }

    update_camerastream(null);

}

/**
 * Send command to play audio
 * @param {number} index 1 - 5
 */
function send_play_audio(index){
    let cmd = JSON.stringify({
        command: "PLAY AUDIO",
        data: index
    });
    if (ws){
        if (ws.readyState === WebSocket.OPEN){
            ws.send(cmd);
        } else console.log("WebSocket is not open");
    } else if (socketio){
        if (socketio.connected){
            socketio.emit("message",cmd);
        } else console.log("Socket.io is not connected");
    }

}

function send_unmute(){
    let cmd = JSON.stringify({
        command: "UNMUTE",
        data: 0
    });
    if (ws){
        if (ws.readyState === WebSocket.OPEN){
            ws.send(cmd);
        } else console.log("WebSocket is not open");
    } else if (socketio){
        if (socketio.connected){
            socketio.emit("message",cmd);
        } else console.log("Socket.io is not connected");
    }

}

function send_mute(){
    let cmd = JSON.stringify({
        command: "MUTE",
        data: 0
    });
    if (ws){
        if (ws.readyState === WebSocket.OPEN){
            ws.send(cmd);
        } else console.log("WebSocket is not open");
    } else if (socketio){
        if (socketio.connected){
            socketio.emit("message",cmd);
        } else console.log("Socket.io is not connected");
    }

}

function send_tilt_up(){
    let cmd = JSON.stringify({
        command: "TILT UP",
        data: tilt_speed
    });
    if (ws){
        if (ws.readyState === WebSocket.OPEN){
            ws.send(cmd);
            btn_center_off()
        } else console.log("WebSocket is not open");
    } else if (socketio){
        if (socketio.connected){
            socketio.emit("message",cmd);
            btn_center_off()
        } else console.log("Socket.io is not connected");
    }

}

function send_tilt_down(){
    let cmd = JSON.stringify({
        command: "TILT DOWN",
        data: tilt_speed
    });
    if (ws){
        if (ws.readyState === WebSocket.OPEN){
            ws.send(cmd);
            btn_center_off()
        } else console.log("WebSocket is not open");
    } else if (socketio){
        if (socketio.connected){
            socketio.emit("message",cmd);
            btn_center_off()
        } else console.log("Socket.io is not connected");
    }

}

function send_pan_left(){
    let cmd = JSON.stringify({
        command: "PAN LEFT",
        data: pan_speed
    });
    if (ws){
        if (ws.readyState === WebSocket.OPEN){
            ws.send(cmd);
            btn_center_off();
        } else console.log("WebSocket is not open");
    } else if (socketio){
        if (socketio.connected){
            socketio.emit("message",cmd);
            btn_center_off();
        } else console.log("Socket.io is not connected");
    }

}

function send_pan_right(){
    let cmd = JSON.stringify({
        command: "PAN RIGHT",
        data: pan_speed
    });
    if (ws){
        if (ws.readyState === WebSocket.OPEN){
            ws.send(cmd);
            btn_center_off()
        } else console.log("WebSocket is not open");
    } else if (socketio){
        if (socketio.connected){
            socketio.emit("message",cmd);
            btn_center_off()
        } else console.log("Socket.io is not connected");
    }

}

function send_stop_movement(){
    let cmd = JSON.stringify({
        command: "STOP MOVEMENT",
        data: 0
    });
    if (ws){
        if (ws.readyState === WebSocket.OPEN){
            ws.send(cmd);
        } else console.log("WebSocket is not open");
    } else if (socketio){
        if (socketio.connected){
            socketio.emit("message",cmd);
        } else console.log("Socket.io is not connected");
    }

}

function send_set_zoom(value){
    let cmd = JSON.stringify({
        command: "SET ZOOM",
        data: value
    });
    if (ws){
        if (ws.readyState === WebSocket.OPEN){
            ws.send(cmd);
        } else console.log("WebSocket is not open");
    } else if (socketio){
        if (socketio.connected){
            socketio.emit("message",cmd);
        } else console.log("Socket.io is not connected");
    }

}

function send_set_volume(value){
    let cmd = JSON.stringify({
        command: "SET VOLUME",
        data: value
    });
    if (ws){
        if (ws.readyState === WebSocket.OPEN){
            ws.send(cmd);
        } else console.log("WebSocket is not open");
    } else if (socketio){
        if (socketio.connected){
            socketio.emit("message",cmd);
        } else console.log("Socket.io is not connected");
    }

}

function btn_center_off(){
    $('#btn_center').prop("className", "btn-center-unactive fa-solid fa-circle");
}

function set_zoom(){
    send_set_zoom($('#zoom').val());
}

function set_volumeoutput(value){
    $('#volumebarvalue').val(value);
    send_set_volume(value);
}

function set_pan_speed(value){
    pan_speed = value;
    clearpan();
    let classvalue = "btn btn-dark btn-sm";
    switch(pan_speed){
        case 16:
            $('#pan1').prop("className", classvalue );
            break;
        case 32:
            $('#pan2').prop("className", classvalue);
            break;
        case 48:
            $('#pan3').prop("className", classvalue);
            break;
        case 63:
            $('#pan4').prop("className", classvalue);
            break;
    }

}

function set_tilt_speed(value){
    tilt_speed = value;
    cleartilt();
    let classvalue = "btn btn-dark btn-sm";
    switch (tilt_speed){
        case 16:
            $('#tilt1').prop("className", classvalue);
            break;
        case 32:
            $('#tilt2').prop("className", classvalue);
            break;
        case 48:
            $('#tilt3').prop("className", classvalue);
            break;
        case 63:
            $('#tilt4').prop("className", classvalue);
            break;
    }
}

// Pan Tilt Speed
function clearpan(){
    for(let i = 1; i <= 4; i++){
        $('#pan'+i).prop("className", "btn btn-outline-dark btn-sm");
    }
}



function cleartilt(){
    for(let i = 1; i <= 4; i++){
        $('#tilt'+i).prop("className", "btn btn-outline-dark btn-sm");
    }
}

function change_video_quality(){
    let btn = document.getElementById("quality_video")
    video_quality = btn.checked?"HQ":"LQ";
}

/**
 * Process Command
 * @param {{reply: string, data: string, additional: string}}dx
 */
function process_command(dx){
    switch (dx.reply){
        case "GET BASE64":
            if (dx.data.startsWith("data:image/jpeg;base64,")){
                update_camerastream(dx.data);
            } else update_camerastream(null);
            if (dx.additional && dx.additional.length>0){
                let stat = JSON.parse(dx.additional);
                if (Array.isArray(stat) && stat.length === 3){
                    $('#streaming_status').html("Streaming at "+stat[0]+"x"+stat[1]+" "+stat[2]+"fps");
                }
            }
            break;
        case "SET VOLUME":
            //console.log("Set Volume: "+dx.data);
            break;
        case "GET VOLUME":
            //console.log("Get Volume: "+dx.data);
            $('#customRange').val(dx.data);
            break;
        case "GET MAX ZOOM":
            $zoom
                .prop("min", 1)
                .prop("max", dx.data);
            break;
        case "GET ZOOM":
            $zoom.val(dx.data);
            break;
        case "GET RESOLUTION":
            //console.log("Get Resolution: "+dx.data);
            break;
        case "PAN LEFT":
            //console.log("Pan Left");
            break;
        case "PAN RIGHT":
            //console.log("Pan Right");
            break;
        case "TILT UP":
            //console.log("Tilt Up");
            break;
        case "TILT DOWN":
            //console.log("Tilt Down");
            break;
        case "STOP MOVEMENT":
            //console.log("Stop Movement");
            break;
        case "SET ZOOM":
            //console.log("Set Zoom: "+dx.data);
            break;
        case "PLAY AUDIO":
            //console.log("Play Audio: "+dx.data);
            if (dx.data.startsWith("Failed")){
                alert(dx.data);
            } else $('#status_player').html("Playing Audio "+dx.data);
            break;
        case "STOP AUDIO":
            //console.log("Stop Audio");
            document.getElementById("status_player").innerHTML = "Stop Playback";
            break;
        case 'SET VIDEO QUALITY':
            //console.log("Set Video Quality: "+dx.data);
            break;
        case "MUTE":
            //console.log("Mute");
            $mute.prop("className", "btn-mute hide");
            $unmute.prop("className", "btn-mute show");
            break;
        case "UNMUTE":
            //console.log("Unmute");
            $mute.prop("className", "btn-mute show");
            $unmute.prop("className", "btn-mute hide");
            break;
        case "GET SYSTEM INFO":
            //console.log("Get System Info: "+dx.data);
            /**
             * @type {{cpu_temperature: string, ram_usage: string, cpu: string, cpu0: string, cpu1: string, cpu2: string, cpu3: string}} systeminfo
             */
            let systeminfo = JSON.parse(dx.data);
            if (systeminfo.cpu_temperature && systeminfo.cpu_temperature.length>0) $('#cpu_temperature').html(`${systeminfo.cpu_temperature} °C`);
            if (systeminfo.cpu && systeminfo.cpu.length>0) $('#cpu_usage').html(`${systeminfo.cpu} %`);
            if (systeminfo.ram_usage && systeminfo.ram_usage.length>0) $('#ram_usage').html(`${systeminfo.ram_usage} %`);
            if (systeminfo.end0_TX && systeminfo.end0_TX.length>0) $('#ethernet_TX').html(systeminfo.end0_TX);
            if (systeminfo.end0_RX && systeminfo.end0_RX.length>0) $('#ethernet_RX').html(systeminfo.end0_RX);
            break;
        case "GET AUDIOFILES":
            //console.log("Get Audio Files: "+dx.data);
            let audiofiles = JSON.parse(dx.data);
            if (audiofiles.preset1 && audiofiles.preset1.length>0 && audiofiles.preset1!== "null") {
                files[0] = audiofiles.preset1;
                $('#desc_content1').html(audiofiles.preset1);
                play_on(1);
            } else {
                files[0] = null;
                $('#desc_content1').html("");
                play_off(1);
            }
            if (audiofiles.preset2 && audiofiles.preset2.length>0 && audiofiles.preset2!== "null") {
                files[1] = audiofiles.preset2;
                $('#desc_content2').html(audiofiles.preset2);
                play_on(2);
            } else {
                files[1] = null;
                $('#desc_content2').html("");
                play_off(2);
            }
            if (audiofiles.preset3 && audiofiles.preset3.length>0 && audiofiles.preset3!== "null") {
                files[2] = audiofiles.preset3;
                $('#desc_content3').html(audiofiles.preset3);
                play_on(3);
            } else {
                files[2] = null;
                $('#desc_content3').html("");
                play_off(3);
            }
            if (audiofiles.preset4 && audiofiles.preset4.length>0 && audiofiles.preset4!== "null") {
                files[3] = audiofiles.preset4;
                $('#desc_content4').html(audiofiles.preset4);
                play_on(4);
            } else {
                files[3] = null;
                $('#desc_content4').html("");
                play_off(4);
            }
            if (audiofiles.preset5 && audiofiles.preset5.length>0 && audiofiles.preset5!== "null") {
                files[4] = audiofiles.preset5;
                $('#desc_content5').html(audiofiles.preset5);
                play_on(5);
            } else {
                files[4] = null;
                $('#desc_content5').html("");
                play_off(5);
            }
            break;

    }
}





