﻿/**************
 * Data Type
 *************/
/*
function DataType(id, name) {
    this.id = id;
    this.name = name;
}

DataType.prototype.isScalar = function() {
    return (this.name == 'scalar' || this.id == 1);
}

DataType.prototype.isImageURL = function() {
    return (this.name == 'image' || this.id == 7);
}

var dataTypeListByID = new Object();
dataTypeListByID[0] = new DataType(0, 'unknown');
dataTypeListByID[1] = new DataType(1, 'scalar');
dataTypeListByID[2] = new DataType(2, 'bmp');
dataTypeListByID[3] = new DataType(3, 'jpg');
dataTypeListByID[4] = new DataType(4, 'gif');
dataTypeListByID[5] = new DataType(5, 'vector');
dataTypeListByID[6] = new DataType(6, 'html');
dataTypeListByID[7] = new DataType(7, 'image');
*/

/**************
 * Sensor Type
 *************/
function getValueIcon(value, min, max, resolution, colorMapIndex, isContinuous) {
    var temp = new Array();
    temp.push('shapes/ColorDot.aspx?');
    temp.push('continuous=' + isContinuous);
    temp.push('&colorMapId=' + colorMapIndex);
    temp.push('&min=' + min);
    temp.push('&max=' + max);
    temp.push('&reso=' + resolution);
    temp.push('&value=' + value);
    return temp.join('');
}

function SensorType(id, name, uri, sensorName, unit, icon, brokenIcon, aggrIcon, valueIconFn, dataType, inView) {
    this.id = id;
    this.name = name;
    this.uri = uri;
    this.sensorName = sensorName;
    this.unit = unit;
    this.icon = icon;
    this.brokenIcon = brokenIcon;
    this.aggrIcon = aggrIcon;
    this.valueIconFn = valueIconFn;
    this.dataType = dataType || 'unknown';
    this.inView = inView || true;
}

/*********************
 * Vector Sensor Type
 *********************/

function VectorSensorType(id, name, uri, sensorName, unit, icon, brokenIcon, aggrIcon, valueIcon, signature) {
    this.superclass(id, name, uri, sensorName, unit, icon, brokenIcon, aggrIcon, valueIcon);
    this.signature = signature;
    var temp = signature.split(';');
    for (var i in temp) {
        if (temp[i] && temp[i].length != 0)
            this.componentTypes.push(sensorTypeListByID[temp[i]]);
    }
}

VectorSensorType.prototype = new SensorType();
VectorSensorType.prototype.superclass = SensorType;
VectorSensorType.prototype.componentTypes = new Array();


var sensorTypeListByID = new Object();
var sensorTypeListByUri = new Object();

var initSensorTypesCount = 0;
function InitSensorTypes() {
    SenseWeb.SensorManagement.GetSensorTypeList(GetSensorTypeDone, GetSensorTypeTimeOut);
    SenseWeb.SensorManagement.GetVectorSensorTypeList(GetSensorTypeDone, GetSensorTypeTimeOut);
}

function InitSensorTypesDone() {
}

function GetSensorTypeDone(result) {
    for (var index in result) {
        var temp = result[index];
        if (temp.DataType == 'vector')
            sensorTypeListByID[temp.ID] = new VectorSensorType(temp.ID
                , temp.Name
                , temp.URI
                , temp.Name + ' Sensor'
                , temp.Unit
                , temp.IconURL
                , temp.BrokenIconURL
                , temp.GroupIconURL
                , temp.IconURL
                , temp.Signature);
        else {
            var valueIcon = getValueIcon;
            if (temp.DataType != 'scalar')
                valueIcon = temp.IconURL;
            sensorTypeListByID[temp.ID] = new SensorType(temp.ID
                , temp.Name
                , temp.URI
                , temp.Name + ' Sensor'
                , temp.Unit
                , temp.IconURL
                , temp.BrokenIconURL
                , temp.GroupIconURL
                , valueIcon
                , temp.DataType);
        }
        sensorTypeListByUri[temp.URI] = sensorTypeListByID[temp.ID];
    }
    initSensorTypesCount ++;
    if (initSensorTypesCount == 2) {
        InitSensorTypesDone();
    }
}
function GetSensorTypeTimeOut() {
    alert("Fail to fetch sensor types!");
}

/**************
 * Sensor
 *************/

function Sensor(name, latitude, longitude, sensorTypeUri, keywords, desc, publisher, state, dataTypeName, timeStamp, webServiceUrl) {
    this.name = name || '';
    this.latitude = latitude || 0;
    this.longitude = longitude || 0;
    this.sensorTypeUri = sensorTypeUri || 0;
    this.keywords = keywords || '';
    this.desc = desc || '';
    this.publisher = publisher || '';
    this.state = state || Sensor.notWorkingStr;
    this.dataTypeName = dataTypeName || 0;
    this.timeStamp = timeStamp;
    this.webServiceUrl = webServiceUrl || 'http://localhost/SenseWebV3/DataHub/Service.asmx';    
}

Sensor.fromString = function(sensorCsv) {
    if ( (sensorCsv != null) && (sensorCsv.length > 0) )
    {
        var sensorAttributes =
            sensorCsv.replace(/\$(?=\$)/g, '\$ ').replace(/([^#])\$/g, '$1$1\$').split(/[^#]\$/);   
        
        if (sensorAttributes != null && sensorAttributes.length >= 9)
        {
            // CSV is received in the following format:
            // 0 [name]
            // 1 [sensorType]
            // 2 [unit]
            // 3 [lat]
            // 4 [long]
            // 5 [desc]
            // 6 [keywords]
            // 7 [pub]
            // 8 [dataType]
            // 9 [state]
            // 10 numSensors 10 timeStamp
            // 11 stateSum 11 webServiceUrl
            // 12 stateMin
            // 13 stateMax

            var name = sensorAttributes[0];
            var sensorTypeUri = sensorAttributes[1];
            var latitude = parseFloat(sensorAttributes[3]);
            var longitude = parseFloat(sensorAttributes[4]);
            var desc = sensorAttributes[5];
            var keywords = sensorAttributes[6];
            var publisher = sensorAttributes[7];
            var dataTypeName = sensorAttributes[8];
            var state = sensorAttributes[9];
            var timeStamp;
            var webServiceUrl;
            var numSensors;
            var stateSum;
            var stateMin;
            var stateMax;

            if (sensorAttributes.length < 14)
            {
                timeStamp = sensorAttributes[10];
                webServiceUrl = sensorAttributes[11];
                return new Sensor(name, latitude, longitude, sensorTypeUri, keywords, 
                    desc, publisher, state, dataTypeName, timeStamp, webServiceUrl);
            } else {
                numSensors = parseInt(sensorAttributes[10]);
                stateSum = parseFloat(sensorAttributes[11]);
                stateMin = parseFloat(sensorAttributes[12]);
                stateMax = parseFloat(sensorAttributes[13]);
                return new SensorGroup(name, latitude, longitude, sensorTypeUri, keywords, 
                    desc, publisher, state, dataTypeName, 
                    numSensors, stateSum, stateMin, stateMax);
            }
        }
    }
}

Sensor.prototype.updateState = function(sensorDataCSV) {
    if (sensorDataCSV) {
        var dataFields = sensorDataCSV.split(/\$/);   
        this.state = dataFields[3] || Sensor.notWorkingStr;
        this.timeStamp = dataFields[2];
    }
}

Sensor.prototype.notWorking = function() {
    return (!this.state || this.state.length == 0 || this.state == ' ');
}

Sensor.prototype.getIcon = function() {
    if (this.notWorking()) {
        return sensorTypeListByUri[this.sensorTypeUri].brokenIcon;
    } else {
        return sensorTypeListByUri[this.sensorTypeUri].icon;
    }
}

Sensor.prototype.getTitle = function() {
    return sensorTypeListByUri[this.sensorTypeUri].sensorName;
}
Sensor.prototype.getValueIcon = function(min, max, resolution, colorMapIndex, isContinuous) {
    var temp = sensorTypeListByUri[this.sensorTypeUri].valueIconFn;
    if (typeof temp != 'function') {
        return this.getIcon();
    } else {
        return temp(this.state, min, max, resolution, colorMapIndex, isContinuous);
    }
}
Sensor.prototype.getDisplayName = function() {
    if (this.displayName) return this.displayName;
    // get display name
    var temp = this.name.lastIndexOf('@');
    this.displayName = sensorTypeListByUri[this.sensorTypeUri].name;
    if (temp == -1) {
        this.displayName += ' (' + this.name + ')';
    } else {
        this.displayName = this.name.substring(temp+1, this.name.length) + ' ' + this.displayName;
        this.displayName += ' (' + this.name.substring(0, temp) + ')';
    }
    return this.displayName;
}

Sensor.prototype.getStateHTML = function(mode3d) {
    if (this.dataTypeName == 'vector') return '';
    var output = new Array();
    if (this.notWorking()) {
        output.push('&nbsp;&nbsp;&nbsp;&nbsp;');
        output.push('not available');
    } else {
        switch (this.dataTypeName) {
            case 'scalar':
                output.push('&nbsp;&nbsp;');
                output.push(Math.round(this.state * 1000) / 1000 + sensorTypeListByUri[this.sensorTypeUri].unit);
                output.push('<br />&nbsp;&nbsp;' + this.timeStamp);
                break;
        }
    }
    output.push('<br />');
    return output.join('');
}

Sensor.prototype.getMetaDetailHTML = function() {
    var output = new Array();
    output.push('<div style="color: #000000; font-weight: bold">' + sensorTypeListByUri[this.sensorTypeUri].sensorName + '</div>');
    output.push('Name: ' + this.name + '<br>');
    output.push('<b>Data:</b><br />');
    return output.join('');
}

Sensor.prototype.getDetailHTML = function(mode3d) {
    var output = new Array();
    output.push(this.getMetaDetailHTML());
    output.push(this.getStateHTML(mode3d));
    return output.join('');
}

Sensor.prototype.getComponentMetaDetailHTML = function() {
    var output = new Array();
    output.push('<div style="color: #000000; font-weight: bold">Assorted Sensors</div>');
    output.push('Publisher: ' + this.publisher + '<br>');
    output.push('Description: ' + this.desc + '<br>');
    return output.join('');
}

Sensor.prototype.getComponentStateHTML = function() {
    var output = new Array();
    output.push('<b>');
    output.push(this.name.substring(this.name.lastIndexOf('@') + 1, this.name.length + 1));
    output.push('&nbsp;');
    output.push(sensorTypeListByUri[this.sensorTypeUri].name);
    output.push('</b>');
    output.push('&nbsp;');
    output.push(this.getStateHTML());
    return output.join('');
}

/**************
 * Sensor: SensorGroup
 *************/

function SensorGroup(name, latitude, longitude, sensorTypeUri, keywords, desc, publisher, state, dataTypeName, numSensors, stateSum, stateMin, stateMax) {
    this.superclass(name, latitude, longitude, sensorTypeUri
        , keywords, desc, publisher, state, dataTypeName);
    this.numSensors = numSensors || 1;
    this.stateSum = stateSum || 0;
    this.stateMin = stateMin || 0;
    this.stateMax = stateMax || 0;
}

SensorGroup.prototype = new Sensor();
SensorGroup.prototype.superclass = Sensor;

SensorGroup.prototype.getIcon = function() {
    return sensorTypeListByUri[this.sensorTypeUri].aggrIcon;
}

SensorGroup.prototype.getTitle = function() {
    return sensorTypeListByUri[this.sensorTypeUri].sensorName + ' Group';
}

SensorGroup.prototype.getStateHTML = function() {
    var output = new Array();
    switch (this.dataTypeName) {
        case 'scalar':
            if (this.stateMin < this.stateMax) {
                output.push('Average: ');
                output.push(Math.round(this.stateSum / this.numSensors * 100) / 100);
                output.push(sensorTypeListByUri[this.sensorTypeUri].unit);
                output.push('<br>');

                output.push('Min: ' + Math.round(this.stateMin * 100) / 100);
                output.push(sensorTypeListByUri[this.sensorTypeUri].unit);
                output.push('<br>');

                output.push('Max: ' + Math.round(this.stateMax * 100) / 100);
                output.push(sensorTypeListByUri[this.sensorTypeUri].unit);
                output.push('<br>');
            }
             break;
    }
    return output.join('');
}

SensorGroup.prototype.getMetaDetailHTML = function() {
    var output = new Array();
    output.push('<div style="color: #000000; font-weight: bold">');
    output.push(sensorTypeListByUri[this.sensorTypeUri].sensorName);
    output.push(' Group</div>');
    output.push('Number in group: ' + this.numSensors + '<br>');
    return output.join('');
}

SensorGroup.prototype.getDetailHTML = function() {
    var output = new Array();
    output.push(this.getMetaDetailHTML());
    output.push(this.getStateHTML());
    return output.join('');
}