@page
@model IndexModel
@{
    Layout = null;
    // ViewData["Title"] = "Home page";
}
<!doctype html>
<html>
	<head>
        <title>Traffic Light Simulation Frontend</title>
        <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto+Condensed:normal,bold,italic" />
        <style>
        body {
            font-family: 'Roboto Condensed';
        }
        .wrapper {
            display: flex;
            max-width: 600px;
            font-family: 'Roboto Condensed';
        }
        .wrapper > div {
            margin: .1em;
            align-self: center;
            flex: 1;
            text-align: center;
        }
        div.light {
            background-size: 100px;
            background-repeat: no-repeat;
            min-height: 230px;
            min-width: 100px;
            width: 100px;
        }
        div.north {
            background-image: url(/images/red.png);
        }
        span#state-data {
            color: #666666;
            font-family: monospace;
        }
        </style>
    </head>
	<body>
		<h1>Traffic light Simulation Demo</h1>
		<p><strong>Period: </strong><span id="period">Awaiting first update...</span></p>
		<p><strong>Simulation time: </strong><span id="time">Awaiting first update...</span></p>
		<p><strong>Current state index: </strong><span id="state-index">Awaiting first update...</span></p>
		<p><strong>Current state data: </strong><span id="state-data">Awaiting first update...</span></p>
        <hr />
		<p><strong>Time until next update: </strong><span id="time-remaining">Awaiting first update...</span> second(s)</p>
		<p><strong>Time factor: </strong><span id="time-factor">Awaiting first update...</span></p>
		<hr />
		<div class="wrapper">
			<div></div>
			<div>NORTH</div>
			<div id="north" class="light north"></div>
			<div id="north-right" class="light"></div>
			<div></div>
			<div></div>
		</div>
		<div class="wrapper">
			<div>WEST</div>
			<div id="west" class="light"></div>
			<div></div>
			<div></div>
			<div></div>
			<div id="east" class="light"></div>
			<div>EAST</div>
		</div>
		<div class="wrapper">
			<div></div>
			<div>SOUTH</div>
			<div id="south" class="light"></div>
			<div></div>
			<div></div>
			<div></div>
		</div>
        <script>
            function sleep(ms)
            {
                return new Promise(resolve => setTimeout(resolve, ms))
            }

            async function ready()
            {
                const req = new XMLHttpRequest();
                const MIN_UPDATE_TIME_MS = 100;

                let isSending = false;
                let nextUpdateTime = Date.now() + 1;

                let timeFactor = null;
                let lastSimulationTimestamp = null;
                let lastUpdateTimestamp = null;

                req.onload = function() 
                {
                    if (this.status !== 200)
                    {
                        console.log("Failed update: status " + this.status);
                        return;
                    }
                    let static_path_prefix = "/images/";
                    let now = Date.now()

                    let light_status = JSON.parse(this.responseText);

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

                    document.getElementById("period").innerHTML = light_status.currentPeriod['verbose-name'];

                    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["north-right"] + "-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);

                    nextUpdateTime = light_status.nextChangeoverTimestampMs;
                    isSending = false;
                };


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

                    if (!isSending && now >= nextUpdateTime)
                    {
                        isSending = true;
                        req.open("GET", "/GetStatus", false);

                        // Note try/catch is the only way to account for net::ERR_CONNECTION_REFUSED - this is NOT dealt with by XMLHttpRequest event hooks.
                        // In the case of net::ERR_CONNECTION_REFUSED should throw DOMException with name "NetworkError".
                        try
                        {
                            req.send();
                        }
                        catch (err)
                        {
                            console.dir(err);
                        }
                    }
                    // 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
                    document.getElementById("time-remaining").innerHTML = Math.max(0, (nextUpdateTime - now) / 1000).toFixed(3);
                    document.getElementById("")

                    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));
                }
            }

            document.addEventListener("DOMContentLoaded", ready);
        </script>
	</body>
</html>
