/******************************************************************************
* Web based vehicle tracker based on Freematics Hub
* Developed by Stanley Huang https://www.facebook.com/stanleyhuangyc
* Distributed under BSD license
* Visit http://freematics.com/hub/api for Freematics Hub API reference
* To obtain your Freematics Hub server key, contact support@freematics.com.au
* 
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/

$(function () {
    $(document).ready(function () {
        OSMAP.init("map");
        self.setTimeout("HUB.loadChannels()", 0);

        var options = {
            enableHighAccuracy: true,
            timeout: 10000,
            maximumAge: 10000,
        };
        navigator.geolocation.getCurrentPosition(
            function (pos) {
                OSMAP.setCenter([pos.coords.latitude, pos.coords.longitude]);
            }, null, options);

        self.setInterval(function () {
            if (HUB.latestMapCenter) OSMAP.setCenter(HUB.latestMapCenter);
        }, MAP_CENTERING_INTERVAL);
    });
});

if (window.require) {
    const shell = require('electron').shell;

    function openLink(url) {
        shell.openExternal(url);
    }
}

function onResize()
{
    var mapHeight = window.innerHeight - document.getElementById("list").offsetHeight - 8;
    if (mapHeight < 300) mapHeight = 300;
    document.getElementById("map").style.height = mapHeight + "px";
}

var HUB = {
	xhr: new XMLHttpRequest(),
	dataSlideIndex: new Array,
	dataSlideLastTick: new Array,
	dataSlideLocked: new Array,
    channelInfo: new Array,
	channelCount: 0,
	channelToReload: true,
	xslChannelList: transport.getXML("list.xsl"),
	latestChannel: null,
	latestMapCenter: null,
	setText: function(name, index, text)
	{
		document.getElementById("data_" + name + index).innerText = text;
	},
	setHTML: function(name, index, html)
	{
		document.getElementById("data_" + name + index).innerHTML = html;
	},
	setTempBar: function(name, index, temp)
	{
		if (temp < 0) temp = 0;
		if (temp > 80) temp = 80;
		var i = Math.floor((temp / 80) * 45) * 34;
		var img = document.getElementById("data_" + name + index);
		img.style.marginLeft = (-i) + "px";
		img.title = temp + "C";
	},
	togglePID: function (index, locked)
	{
	    if (!locked) this.dataSlideLastTick[index] = null;
	    this.dataSlideLocked[index] = locked;
	},
	getPIDValue: function (data, pid)
	{
		for (var i = 0; i < data.length; i++) {
			if (data[i][0] == pid) {
				return PID.normalize(pid, data[i][1]);
			}
		}
		return null;
	},
	updateChannel: function (index, ch)
	{
		if (!document.getElementById("data_elapsed" + index)) {
			channelToReload = true;
			return;
		}
		this.channelInfo[index] = ch;
		var parked = ch.parked || ch.age > TRIP_END_TIMEOUT;
		if (parked) { 
			this.setText("elapsed", index, getHHMM(Math.floor(ch.age / 1000)));
			this.setText("state", index, "PARKED");
			this.setHTML("info", index, ch.vin + "<br/>");
			this.setText("rate", index, "-");
			this.setText("delay", index, "-");
			this.setText("pid_value", index, "");
			this.setText("pid_name", index, "");
			return;
		}
		this.setText("elapsed", index, getHHMMSS(ch.elapsed));
		this.setText("state", index, "RUNNING");
		if (ch.data.length > 0) {
		    // live data available
		    var lastTick = this.dataSlideLastTick[index];
		    if (this.dataSlideIndex[index] == null) {
		        this.dataSlideIndex[index] = 0;
		        this.dataSlideLastTick[index] = ch.tick;
		    } else if (!this.dataSlideLocked[index] && (lastTick == null || ch.tick > lastTick + DATA_SLIDE_INTERVAL || ch.tick < lastTick)) {
		        this.dataSlideLastTick[index] = ch.tick;
		        // switch to next data
		        this.dataSlideIndex[index]++;
		    }
		    if (this.dataSlideIndex[index] >= ch.data.length) this.dataSlideIndex[index] = 0;
		    var dataIndex = this.dataSlideIndex[index];
		    var pid = ch.data[dataIndex][0];
		    var value = ch.data[dataIndex][1];
		    this.setText("pid_value", index, PID.normalize(pid, value));
		    this.setText("pid_name", index, PID.getNameUnit(pid));
		}
		this.setHTML("info", index, ch.vin + "<br/>" + ch.ip);
		this.setText("rate", index, ch.rate);
		this.setText("delay", index, ch.age);
		this.setText("recv", index, Math.floor(ch.recv / 1024));
		this.setText("distance", index, (ch.distance / 1000).toFixed(1));
		
		var deviceTemp = this.getPIDValue(ch.data, PID.DEVICE_TEMP);
		if (deviceTemp != null) {
			this.setTempBar("temp", index, deviceTemp);
		}
		
	    // update map
		var latlng = [this.getPIDValue(ch.data, PID.GPS.LATITUDE), this.getPIDValue(ch.data, PID.GPS.LONGITUDE)];
		if (latlng[0]) {
		    OSMAP.setMarker(index, latlng);
		    OSMAP.setTooltip(index, ch.vin);
		    // find out the channel with latest location data
		    if (this.latestChannel) {
		        if (ch.age < this.latestChannel.age) {
		            this.latestChannel = ch;
		        }
    		} else {
		        this.latestChannel = ch;
		    }
		    this.latestMapCenter = latlng;
        }
	},
	loadChannels: function()
	{
		if (this.channelToReload) {
			// need to refresh channel list
			this.refreshList();
			this.channelToReload = false;
		}
		this.xhr.onreadystatechange = function() {
			if (this.readyState != 4) return;
			if (this.status != 200) {
				if (this.status) {
					alert("Server under maintenance (status: " + this.status + ")");
				}
				return;
			}
			var chdata = JSON.parse(this.responseText);
			if (chdata.channels.length != HUB.channelCount) {
				HUB.channelCount = chdata.channels.length;
				HUB.channelToReload = true;
			} else {
				for (var i = 0; i < chdata.channels.length; i++) {
				    if (!chdata.channels[i].id) continue;
					HUB.updateChannel(chdata.channels[i].id, chdata.channels[i]);
				}
			}
			self.setTimeout("HUB.loadChannels()", LIST_REFRESH_INTERVAL);
		};
		var url = serverURL + "channels?data=1";
		this.xhr.open('GET', url, true);    
		this.xhr.send(null);
	},
	refreshList: function ()
	{
		var xml = transport.getXML(serverURL + "channels.xml");
		transformXML(xml, this.xslChannelList, "list");
		onResize();
	},
	viewChannel: function(id)
	{
	    if (!id) return;
	    if (window.require) {
	        openLink("http://localhost:8080/view.html?id=" + id);
	    } else {
	        window.open("view.html?id=" + id, "HubChannel" + id, "width=1000,height=1200,menubar=no,status=no,toolbar=no");
	    }
	}
};
