﻿/* ================================================================== */
/* SensorMapModel.js                                                  */
/*                                                                    */
/* This file contains a prototype definition for a SensorMap model    */
/* and all functions related to maintaining model state.              */
/*                                                                    */
/* A SensorMap model consists of a center point, the zoom, the map    */
/* style, sensor filter types, filter terms and a list of filer       */
/* coordinates.                                                       */
/*                                                                    */
/* ================================================================== */

function ColorMapSetting(isContinuous, colorMapIndex, min, max, resolution, inUse) {
    if (isContinuous != null) this.isContinuous = isContinuous;
    if (colorMapIndex != null) this.colorMapIndex = colorMapIndex;
    if (min != null) this.min = min;
    if (max != null) this.max = max;
    if (resolution != null) this.resolution = resolution;
    if (inUse != null) this.inUse = inUse;
}

ColorMapSetting.prototype.isContinuous = true;
ColorMapSetting.prototype.colorMapIndex = 0;
ColorMapSetting.prototype.min = 0;
ColorMapSetting.prototype.max = 100;
ColorMapSetting.prototype.resolution = 10;
ColorMapSetting.prototype.inUse = false;

ColorMapSetting.prototype.update = function(isContinuous, colorMapIndex, min, max, resolution, inUse) {
    if (isContinuous != null) this.isContinuous = isContinuous;
    if (colorMapIndex != null) this.colorMapIndex = colorMapIndex;
    if (min != null) this.min = min;
    if (max != null) this.max = max;
    if (resolution != null) this.resolution = resolution;
    if (inUse != null) this.inUse = inUse;
    else this.inUse = false;
}

ColorMapSetting.prototype.clear = function() {
    this.isContinuous = null;
    this.colorMapIndex = null;
    this.min = null;
    this.max = null;
    this.resolution = null;
    this.inUse = false;
}

var VizTypes = {
    icon: 'Icon'
    , rectangle: 'Rectangle'
    , contour: 'Contour Map'
}

function SensorMapModel(ctrLatitude, ctrLongitude, zoom, style, filterTypes, 
    filterTerms, filterCoords)
{
    this.ctrLatitude = ctrLatitude || SensorMapModel.defaultLatitude;
    this.ctrLongitude = ctrLongitude || SensorMapModel.defaultLongitude;
    this.zoom = zoom || SensorMapModel.defaultZoom;
    this.style = style || SensorMapModel.defaultStyle;
    this.filterTypes = filterTypes || SensorMapModel.getDefaultFilterTypes();
    this.filterTerms = filterTerms || SensorMapModel.defaultFilterTerms;
    this.filterCoords = filterCoords || SensorMapModel.getDefaultFilterCoords();
    this.colorMapSetting = new ColorMapSetting();
    this.timeSetting = new TimeSetting();
    this.vizType = VizTypes.icon;
}

SensorMapModel.defaultLatitude = 47.63497343254649;
SensorMapModel.defaultLongitude = -122.14237021026608;
SensorMapModel.defaultZoom = 11;
SensorMapModel.defaultStyle = VEMapStyle.Road;
SensorMapModel.defaultFilterTerms = '';

SensorMapModel.getDefaultFilterTypes = function ()
{
    var defaultFilterTypes = [];
    
    for (var ii in sensorTypeListByUri)
    {
        defaultFilterTypes[ii] = true;
    }
    
    return defaultFilterTypes;
}

SensorMapModel.getDefaultFilterCoords = function ()
{
    return new Array();
}

/*
 * toString
 *
 * Returns the SensorMap model as a string in the following format:
 * la=<ctrLat>&lo=<ctrLong>&zl=<zoom>&ms=<style>&st=<searchTerms>&tf=<typeFilterArr>&fp=<filterPoints>
 */
SensorMapModel.prototype.toString = function ()
{
    var result = new Array();
    result.push('la=' + this.ctrLatitude + '&lo=' + this.ctrLongitude 
        + '&zl=' + this.zoom + '&ms=' + this.style + '&st=' 
        + escape(this.filterTerms) + '&tf=' + this.getFilteredTypesStr() 
        + '&fp=' + this.getFilterPointsStr());
    
    // add time settings
    if (this.timeSetting.inUse == true) {
        result.push('&stime=' + this.timeSetting.startTime.getTime());
        result.push('&etime=' + this.timeSetting.endTime.getTime());
        result.push('&ctime=' + this.timeSetting.currentTime.getTime());
        result.push('&resoT=' + this.timeSetting.resolution);
    }

    /*
    // add colormap settings
    if (this.colorMapSetting.inUse == true) {
        result.push('&iC=' + this.colorMapSetting.isContinuous);
        result.push('&cMI=' + this.colorMapSetting.colorMapIndex);
        result.push('&min=' + this.colorMapSetting.min);
        result.push('&max=' + this.colorMapSetting.max);
        result.push('&resoC=' + this.colorMapSetting.resolution);
    }
    
    // add visualization type
    result.push('&vT=' + this.vizType);
    */
    
    return result.join('');
}

/*
 * fromString
 *
 * Initializes the SensorMapModel object from a string.
 */
SensorMapModel.prototype.fromString = function (smModelStr)
{
    var args = new Object();
    var pairs = smModelStr.split('&');
    
    for (var ii = 0; ii < pairs.length; ii++)
    {
        var pos = pairs[ii].indexOf('=');
        if (pos == -1)
        {
            continue;
        }
        var argname = pairs[ii].substring(0, pos);
        var value = pairs[ii].substring(pos + 1);
        args[argname] = unescape(value);
    }
    
    this.ctrLatitude = 
        (args.la) ? parseFloat(args.la) : SensorMapModel.defaultLatitude;
    
    this.ctrLongitude = 
        (args.lo) ? parseFloat(args.lo) : SensorMapModel.defaultLongitude;
    
    this.zoom = 
        (args.zl) ? parseInt(args.zl) : SensorMapModel.defaultZoom;

    this.style = 
        (args.ms) ? args.ms : SensorMapModel.defaultStyle;
    
    if (args.tf) 
    { 
        this.setFilteredTypesFromStr(args.tf); 
    }
    else
    {
        this.filterTypes = SensorMapModel.getDefaultFilterTypes();
    }   
    this.filterTerms = 
        (args.st) ? args.st : SensorMapModel.defaultFilterTerms;
        
    if (args.fp) 
    { 
        this.setFilterCoordsFromStr(args.fp); 
    }
    else
    {
        this.filterCoords = SensorMapModel.getDefaultFilterCoords();
    }

    // parse time settings
    if (args.stime) {
        this.timeSetting = new TimeSetting(new Date(parseInt(args.stime))
            , new Date(parseInt(args.etime))
            , new Date(parseInt(args.ctime))
            , args.resoT
            , true);
    } else {
        this.timeSetting = new TimeSetting();
    }

    /*
    // parse colormap settings
    if (args.iC) {
        this.colorMapSetting = new ColorMapSetting(args.iC
            , args.cMI
            , args.min
            , args.max
            , args.resoC
            , true);
    } else {
        this.colorMapSetting = new ColorMapSetting();
    }
    
    // parse visualization type
    if (args.vT) {
        this.vizType = args.vT;
    } else {
        this.vizType = VizTypes.icon;
    }
    */
}

/*
 * getFilteredTypesStr 
 *
 * Returns the type filters in string format.  String is composed of ones and 
 * zeros delimited by commas.  The sequence of ones and zeros in terms of the
 * order that the individual sensor types are stored in Sensor.individualTypes.
 */
SensorMapModel.prototype.getFilteredTypesStr = function ()
{
    var filteredTypesStr = '';
    
    for (var ii in sensorTypeListByUri)
    {
        filteredTypesStr += ((this.filterTypes[ii]) ? '1,' : '0,');
    }
    
    return filteredTypesStr.substr(0, filteredTypesStr.length - 1);
}

/*
 * setFilteredTypesFromStr 
 *
 * Sets SensorMap type filters given a string of ones and zeros.
 */
SensorMapModel.prototype.setFilteredTypesFromStr = function (typeFilterStr)
{
    var typeFilters = typeFilterStr.split(',');
    
    var tf = 0;
    
    for (var ii in sensorTypeListByUri)
    {
        if (tf < typeFilters.length)
        {
            var filterValue = parseInt(typeFilters[tf]);
            this.filterTypes[ii] = ((filterValue == 1) ? true : false);
            tf++;
        }
    }
}

/*
 * getFilterPointsStr 
 *
 * Returns pins as a sequence of comma-delimited lat, lon pairs.
 */
SensorMapModel.prototype.getFilterPointsStr = function ()
{
    var filterPointsStr = '';
    
    for (var fp = 0; fp < this.filterCoords.length; fp++)
    {
        filterPointsStr += this.filterCoords[fp].Latitude + ',' 
            + this.filterCoords[fp].Longitude 
            + ((fp < this.filterCoords.length - 1) ? ',' : '');
    }
    
    return filterPointsStr;
}

/*
 * setFilterPinsFromStr
 *
 * Sets SensorMap type filters given a string of comma-delimited lat/lon pairs
 * (lat1,lon1,lat2,lon2,...,latn,lonn).
 */
SensorMapModel.prototype.setFilterCoordsFromStr = function (filterPinsStr)
{
    var latlongs = 
        (filterPinsStr.indexOf(',') >= 0) ? filterPinsStr.split(',') : [];
        
    if (latlongs.length % 2 != 0)
    {
        return;
    }
    
    this.filterCoords = [];
    
    for (var fp = 0; fp < latlongs.length; )
    {
        var lat = parseFloat(latlongs[fp]);
        var lon = parseFloat(latlongs[fp + 1]);
        
        this.filterCoords.push(new VELatLong(lat, lon));
        
        fp += 2;
    }   
}

/*
 * deleteFilterPoint
 *
 * Deletes a filter point from the SensorMap model filter coordinate list.
 */
SensorMapModel.prototype.deleteFilterPoint = function(index)
{
    var polyPoints = [];
    var ii = 0;
    
    while(ii != index) 
    {
        polyPoints[ii] = smModel.filterCoords[ii];
        ii++;
    }
    
    while(ii + 1 < smModel.filterCoords.length)
    {
        polyPoints[ii] = smModel.filterCoords[ii + 1];
        ii++;
    }
    
    this.filterCoords = polyPoints;
}