"use strict";

var timeFactor = null;
var lastSimulationTimestamp = null;
var lastUpdateTimestamp = null;
var nextUpdateTime = null;

var connection = new signalR.HubConnectionBuilder().withUrl("/lightHub").build();

//Disable the send button until connection is established.
document.getElementById("sendButton").disabled = true;

connection.on("ReceiveStateUpdate", function (stateData) {
    console.log("Update pushed.");
    updateView(stateData);
});

connection.on("ReceiveServerState", function (stateData) {
    console.log("Recevied requested server state...")
    updateView(stateData);
});
    
connection.start().then(function () {
    connection.invoke("GetServerState", connection.connectionId).catch(function (err) {
        return console.error(err.toString());
    });
}).catch(function (err) {
    return console.error(err.toString());
});

document.getElementById("sendButton").addEventListener("click", function (event) {
    var user = document.getElementById("userInput").value;
    var message = document.getElementById("messageInput").value;
    connection.invoke("SendMessage", user, message).catch(function (err) {
        return console.error(err.toString());
    });
    event.preventDefault();
});

document.getElementById("updateButton").addEventListener("click", function (event) {
    var connectionId = connection.connectionId;
    connection.invoke("GetServerState", connectionId).catch(function (err) {
        return console.error(err.toString());
    });
    event.preventDefault();
});

function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms))
}

function updateView(stateData) {
    let now = Date.now();
    let static_path_prefix = "/images/";
    let light_status = stateData;
    // let light_status = JSON.parse(stateData);

    lastSimulationTimestamp = light_status.currentSimulationTimestampMs;
    lastUpdateTimestamp = now;
    timeFactor = light_status.timeFactor;
    nextUpdateTime = light_status.nextChangeoverTimestampMs;

    document.getElementById("period").innerHTML = light_status.currentPeriod.verboseName;

    document.getElementById("state-index").innerHTML = light_status.currentStateIndex;
    document.getElementById("state-data").innerHTML = JSON.stringify(light_status.currentState);

    document.getElementById("north").style.backgroundImage = "url(" + static_path_prefix + light_status.currentState.north + ".png)";
    document.getElementById("north-right").style.backgroundImage = "url(" + static_path_prefix + light_status.currentState.northRight + "-right.png)";
    document.getElementById("west").style.backgroundImage = "url(" + static_path_prefix + light_status.currentState.west + ".png)";
    document.getElementById("east").style.backgroundImage = "url(" + static_path_prefix + light_status.currentState.east + ".png)";
    document.getElementById("south").style.backgroundImage = "url(" + static_path_prefix + light_status.currentState.south + ".png)";
    document.getElementById("time-factor").innerHTML = light_status.timeFactor.toFixed(2);
}

async function ready() {
    const MIN_UPDATE_TIME_MS = 100;
    console.log("Main loop registered");


    while (true) {
        let now = Date.now();

        // Important note: Due to marginal overshoot of scheduled timing, it is possible for time-remaining to be very slightly negative
        // It is undesirable to present this on the frontend, and therefore zero is the lowest number displayed
        if (nextUpdateTime != null) {
            // console.log("Updating time...")
            document.getElementById("time-remaining").innerHTML = Math.max(0, (nextUpdateTime - now) / 1000).toFixed(3);

            if (lastSimulationTimestamp !== null && lastUpdateTimestamp !== null) {
                let simulationDate = new Date(lastSimulationTimestamp + parseInt((now - lastUpdateTimestamp) * timeFactor));
                document.getElementById("time").innerHTML = simulationDate.toUTCString().slice(17, 25); // Time section of date string only
                await sleep(Math.min(MIN_UPDATE_TIME_MS, nextUpdateTime - now));
            }
        }
        else {
            await sleep(250);
        }
    }
}

document.addEventListener("DOMContentLoaded", ready);