/*
(c) 2006 Horizon Marine, Inc.  Marion, MA.  All rights reserved.

This code was developed by Horizon Marine, Inc. and is protected by 
copyright law. You may not copy, retransmit, archive, modify, distribute, 
or exploit any content on iBoatTrack.com. Redistribution of any content 
over any network, construction of a database, or offer for sale of any 
content is prohibited without written permission from Horizon Marine, Inc. 
Content that appears on this website is for personal use only, commercial 
use of the content is strictly prohibited.
*/

/************************************************************************/
/*              Javascript functions related to horzon marine.          */
/************************************************************************/
var goColorClass = null;

//ka-map will automatically register this event
var HM_BOATS_INITIALIZED = gnLastEventId ++;
var HM_CLASS_CHANGED = gnLastEventId ++;
var HM_TIME_CHANGED = gnLastEventId ++;

/**
 * hmBoatManager
 *
 * manage a set of boats
 */
function hmBoatManager( oKaMap )
{
    this.aBoats = [];
    this.aClasses = [];
    this.aTimes = [];
    this.nCurrenttime = 0;
    
    this.nStartTime = -1;
    this.nEndTime = -1;
    
    this.kaMap = oKaMap;
    this.pointCanvas = null;
    this.infoCanvas = null;
        
    this.initialize = hmBoatManager_initialize;
    this.addBoat = hmBoatManager_addBoat;
    this.selectClass = hmBoatManager_selectClass;
    
    this.decrementTimeIndice = hmBoatManager_decrementTimeIndice;
    this.incrementTimeIndice = hmBoatManager_incrementTimeIndice;
    this.setTimeIndice = hmBoatManager_setTimeIndice;
    this.update = hmBoatManager_update;
    this.toggleBoatDisplay = hmBoatManager_toggleBoatDisplay;
        
    this.scaleChanged = hmBoatManager_scaleChanged;

    this.kaMap.registerForEvent( KAMAP_MAP_INITIALIZED, this, this.initialize );
    this.kaMap.registerForEvent( KAMAP_SCALE_CHANGED, this, this.scaleChanged );
}

function hmBoatManager_selectClass()
{
    this.update();
}

function hmBoatManager_initialize()
{
    if (this.pointCanvas == null)
    {
        this.pointCanvas = this.kaMap.createDrawingCanvas(2000);
    }
}

function hmBoatManager_addBoat( oBoat )
{
    if (!this.aClasses[oBoat.class_id])
    {
        this.aClasses[oBoat.class_id] = true;
    }
    oBoat.setManager(this);
    oBoat.drawPoint();
    this.aBoats.push( oBoat );
}

function hmBoatManager_decrementTimeIndice()
{
    if (this.nCurrentTime > 0)
    {
        this.nCurrentTime = this.nCurrentTime -1;
        this.update();
        this.kaMap.triggerEvent( HM_TIME_CHANGED, this.nCurrentTime );
    }
}

function hmBoatManager_incrementTimeIndice()
{
    if (this.nCurrentTime)
    {
        this.nCurrentTime = this.nCurrentTime + 1;
        this.update();
        this.kaMap.triggerEvent( HM_TIME_CHANGED, this.nCurrentTime );
    }
}

function hmBoatManager_setTimeIndice(iIndice)
{
    if (iIndice >= 0)
    {
        this.nCurrentTime = iIndice;
        this.update();
        this.kaMap.triggerEvent( HM_TIME_CHANGED, this.nCurrentTime );
    }
}

function hmBoatManager_update()
{
//    var sel = document.forms[0].lease_areas_goto;
//    sel.length = 0;
//    sel.options[sel.options.length] = new Option('--- Pick a boat ---','',false,false);
    
    for (var i=0; i<this.aBoats.length; i++)
    {
        this.aBoats[i].update();
//        if (this.aBoats[i].class_id == document.forms[0].class_goto[document.forms[0].class_goto.selectedIndex].value
//              || document.forms[0].class_goto.selectedIndex == 1) { 
//          sel.options[sel.options.length] = 
//            new Option(this.aBoats[i].name,this.aBoats[i].sel_idx,false,false);
//        }
    }
}

function hmBoatManager_toggleBoatDisplay(boats)
{
    for (var i=0; i<this.aBoats.length; i++)
    {
        if (boats == 'all' || boats.indexOf(';'+this.aBoats[i].name+';') >= 0) {
          this.aBoats[i].displayed = !(this.aBoats[i].displayed);
          this.aBoats[i].update();
        }
    }
}

function hmBoatManager_scaleChanged( eventID, scale )
{
    // keeping this around for now (cpurvis)
}

var hmBoatInfoDiv = null;

/************************************************************************/
/*                               hmBoatclass                            */
/*                                                                      */
/*      class to contain boat information.                              */
/************************************************************************/
function hmBoat(name, idx, loc, ts, spd, dir, class_id, rgb, sel_idx, 
  skipper_name, design, hail_port, distance_from_finishline_nm,
  nam_wspd_knots, nam_wdir_from_deg)
{
    this.name   = name;
    this.idx    = idx;
    this.loc    = loc;
    this.ts     = ts;
    this.spd    = spd;
    this.dir    = dir;
    this.class_id     = class_id;
    this.sel_idx      = sel_idx;
    this.skipper_name = skipper_name;
    this.design       = design;
    this.hail_port    = hail_port;
    this.distance_from_finishline_nm = distance_from_finishline_nm;
    this.nam_wspd_knots              = nam_wspd_knots;
    this.nam_wdir_from_deg           = nam_wdir_from_deg;

    this.aIdx = [];
    var sIdx = new String(idx);
    var aValues = sIdx.split(';');
    for (var j=0; j<aValues.length; j++)
    {
        this.aIdx.push( aValues[j]);
    }

    this.aLocs = [];
    var sLoc = new String(loc);
    var aLoc = sLoc.split(';');
    for (var j=0; j<aLoc.length; j++) {
      var sLatLong = new String(aLoc[j]);
      var aLatLong = sLatLong.split(',');
      // reproject it here instead of in the DB -- may be dumb, but proj not compiled in to psql right now :(
      var coords = myProj.Forward(Array(aLatLong[0],aLatLong[1]));
      this.aLocs.push( Array(coords[0],coords[1]) );
    }

    this.aTs = [];
    var sTs = new String(ts);
    var aValues = sTs.split(';');
    for (var j=0; j<aValues.length; j++)
    {
        this.aTs.push( aValues[j]);
    }

    this.aSpd = [];
    var sSpd = new String(spd);
    var aValues = sSpd.split(';');
    for (var j=0; j<aValues.length; j++)
    {
        this.aSpd.push( aValues[j]);
    }

    this.aDir = [];
    var sDir = new String(dir);
    var aValues = sDir.split(';');
    for (var j=0; j<aValues.length; j++)
    {
        this.aDir.push( aValues[j]);
    }
    
    this.aDistFinishLine = [];
    var sDistFinishLine = new String(distance_from_finishline_nm);
    var aValues = sDistFinishLine.split(';');
    for (var j=0; j<aValues.length; j++)
    {
        this.aDistFinishLine.push( aValues[j]);
    }
    
    this.aWspdKnots = [];
    var sWspdKnots = new String(nam_wspd_knots);
    var aValues = sWspdKnots.split(';');
    for (var j=0; j<aValues.length; j++)
    {
        this.aWspdKnots.push( aValues[j]);
    }
    
    this.aWdirFrom = [];
    var sWdirFrom = new String(nam_wdir_from_deg);
    var aValues = sWdirFrom.split(';');
    for (var j=0; j<aValues.length; j++)
    {
        this.aWdirFrom.push( aValues[j]);
    }
    
    this.rgb = rgb;
    this.visible = true;
    this.pointImgObj = null; //until draw has been called
        
    this.oManager = null;
    
    this.drawPoint = hmBoat_drawPoint;
    this.update = hmBoat_update;
    this.setManager = hmBoat_setManager;
    this.setVisibility = hmBoat_setVisibility;
    this.showInfo = hmBoat_showInfo;
    this.hideInfo = hmBoat_hideInfo;
    
    this.getIdx = hmBoat_getIdx;
    this.displayed = true;
}

function hmBoat_setVisibility( bVisible )
{
    this.pointImgObj.style.visibility = bVisible ? 'visible':'hidden';
    this.visible = bVisible;
}

function hmBoat_setManager( oManager )
{
    if (this.oManager != null)
    {
        //deregister from existing event?
        this.oManager.kaMap.deregisterForEvent(KAMAP_SCALE_CHANGED,this,this.update);
    }
    this.oManager = oManager;
    this.oManager.kaMap.registerForEvent(KAMAP_SCALE_CHANGED,this,this.update);
    
}

function hmBoat_drawPoint()
{
    if (this.pointImgObj == null)
    {
        this.pointImgObj = hmCreatePointImage(this.rgb,this.name);
        this.pointImgObj.id = this.name;
        //this.pointImgObj.title = this.name;
        //this.pointImgObj.alt = this.name;
        this.pointImgObj.oBoat = this;
        //this.pointImgObj.style.cursor = 'help';
        this.pointImgObj.onmouseover = this.showInfo;
        this.pointImgObj.onmouseout = this.hideInfo;
        //this.pointImgObj.onclick = this.showInfo;
    }
    this.update();
}

function hmBoat_getIdx (ts) {
  var ts_sec = document.forms[0].HMTimeSelector[ts].value;
  for (var i = 0; i < this.aIdx.length; i++) {
    if (this.aIdx[i] >= ts_sec) {
      return(i);
    }
  }
  return(this.aIdx.length - 1);
}

function hmBoat_update()
{
    var oMap = myKaMap.getCurrentMap();
    var sel = document.forms[0].class_goto;

    this.oManager.kaMap.removeObject( this.pointImgObj );

    var isWatched = false;
    for (var j = 0; j < oMap.boatsToWatch.length; j++) {
      var aBoat = oMap.boatsToWatch[j].split('|');
      if (aBoat[0] != 'empty' && aBoat[0].length > 0) {
        if (aBoat[0] == this.name) {
          isWatched = true;
          break;
        }
      }
    }

    if (sel.options.length > 1) {
      if (sel.selectedIndex == 0) {
        this.displayed = isWatched;
      }
      else if (sel.selectedIndex == 1) {
        this.displayed = true;
      }
      else if (sel.selectedIndex > 1) {
        this.displayed = this.class_id == sel[sel.selectedIndex].value || isWatched;
      }
    }
    
    if (this.displayed) {
      var idx = this.getIdx(this.oManager.nCurrentTime);
      this.oManager.kaMap.addObjectGeo(this.oManager.pointCanvas, 
        this.aLocs[idx][0], 
        this.aLocs[idx][1], 
        this.pointImgObj);
    }
    this.hideInfo();
}

function pad_zeroes (digits, n) {  // n is a string or number
  if(n.constructor == Number) n = n.toString();
  while(n.length < digits) n = "0" + n;
  return n;
}

function hmBoat_showInfo( )
{
    var oBoat = this.oBoat?this.oBoat:this;
    
    if (!oBoat)
        return;
    
    if (!hmBoatInfoDiv)
    {
        hmBoatInfoDiv = document.createElement('div');
        hmBoatInfoDiv.oManager = oBoat.oManager;
        hmBoatInfoDiv.style.position = 'absolute';
        hmBoatInfoDiv.style.zIndex = 1;
        hmBoatInfoDiv.isVisible = false;
    }
    
    hmBoat_hideInfo();
    
    // var idx = oBoat.oManager.nCurrentTime;
    var idx = oBoat.getIdx(oBoat.oManager.nCurrentTime);
    
    var name = oBoat.name;
    var skipper_name = 'Skipper</td><td class="mapTipsLabel2">' + oBoat.skipper_name;
    var design = 'Design</td><td class="mapTipsLabel2">' + oBoat.design;
    var hail_port = 'Hail port</td><td class="mapTipsLabel2">' + oBoat.hail_port;

    var class_id = 'Class</td><td class="mapTipsLabel2">'+ oBoat.class_id;
    var position =  'Position</td><td class="mapTipsLabel2">' + -oBoat.aLocs[idx][0] +
                    ' W ' + oBoat.aLocs[idx][1]+' N';
                    
    var Mon3 = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
    var yyyy = oBoat.aTs[idx].substr(0,4);
    var mm   = oBoat.aTs[idx].substr(5,2);
    var dd   = oBoat.aTs[idx].substr(8,2);
    var hh   = oBoat.aTs[idx].substr(11,2);
    var mi   = oBoat.aTs[idx].substr(14,2);

    // think ONLY GMT
    localDate = new Date (yyyy+'/'+mm+'/'+dd+' '+hh+':'+mi+' GMT');
    
    // check to see if difference between this time and the map time is substantial
    mapDate = new Date(Number(document.forms[0].time_stamp_js_epoch.value));
    
    if (Math.abs(mapDate - localDate) > (1*60*60*1000)) {
      var row1_style = 'mapTipsRow1alert';
      var alert_msg  =
        '<tr class="mapTipsRow2">' + 
           '<td class="mapTipsLabelAlert" align="center" colspan="2">This reading is over 1h from the map clock.</td>' +
        '</tr>';
      var time_style = 'mapTipsLabel2Alert';
    }
    else {
      var row1_style = 'mapTipsRow1';
      var alert_msg  = '';
      var time_style = 'mapTipsLabel2';
    }
    
    localDate.setUTCHours(localDate.getUTCHours() - 4);
    niceStr = Mon3[localDate.getUTCMonth()] 
      + ' ' + pad_zeroes(2,localDate.getUTCDate()) 
      + ' ' + pad_zeroes(2,localDate.getUTCHours()) 
      + ':' + pad_zeroes(2,localDate.getUTCMinutes()) + ' EDT';

    var time  = 'Time</td><td class="'+time_style+'">' + niceStr;
    var speed = 'Speed</td><td class="mapTipsLabel2">' + oBoat.aSpd[idx] + ' knots';
    var dir   = '</td><td class="mapTipsLabel2">' + oBoat.aDir[idx];
    var distFinishLine = 'To finish</td><td class="mapTipsLabel2">' + oBoat.aDistFinishLine[idx];
    var nam_wspd_knots = 'Wind</td><td class="mapTipsLabel2">' + oBoat.aWspdKnots[idx] + ' knots';
    var nam_wdir_from_deg = '</td><td class="mapTipsLabel2">' + oBoat.aWdirFrom[idx];
    
    hmBoatInfoDiv.innerHTML = 
    '<table width="160" border="0" cellpadding="0" cellspacing="0" class="mapTipsTable">' +
       '<tr class="'+row1_style+'">' +
         '<td class="mapTipsLabel1">' +
           '<strong>' + name + '&nbsp;</strong>' +
         '</td>' +
         '<td class="mapTipsLabel1_white" align="right">' + 
           '<a href="#" onclick="hmBoat_hideInfo()">' +
           'Close</a>' +
         '</td>' +
       '</tr>' +
    '</table>' +
    '<table width="160" border="0" cellpadding="0" cellspacing="0" class="mapTipsTable">' +
       '<tr class="mapTipsRow2">' + 
           '<td class="mapTipsLabel2" >' + class_id  + '</td>' +
       '</tr>' +
       '<tr class="mapTipsRow2">' + 
           '<td class="mapTipsLabel2" >' + skipper_name  + '</td>' +
       '</tr>' +
       '<tr class="mapTipsRow2">' + 
           '<td class="mapTipsLabel2" >' + design  + '</td>' +
       '</tr>' +
       '<tr class="mapTipsRow2">' + 
           '<td class="mapTipsLabel2" >' + hail_port  + '</td>' +
       '</tr>' +
//       '<tr class="mapTipsRow2">' + 
//           '<td class="mapTipsLabel2" >' + position  + '</td>' +
//       '</tr>' +
       '<tr class="mapTipsRow2">' +
         '<td class="mapTipsLabel2" >' + time + '</td>' +
       '</tr>' +
       '<tr class="mapTipsRow2">' +
         '<td class="mapTipsLabel2" >' + speed + '</td>' +
       '</tr>' +
       '<tr class="mapTipsRow2">' +
         '<td class="mapTipsLabel2" >' + dir + '</td>' +
       '</tr>' +
       '<tr class="mapTipsRow2">' +
         '<td class="mapTipsLabel2" >' + distFinishLine + ' nm</td>' +
       '</tr>' +
       '<tr class="mapTipsRow2">' +
         '<td class="mapTipsLabel2" >' + nam_wspd_knots + '</td>' +
       '</tr>' +
       '<tr class="mapTipsRow2">' +
         '<td class="mapTipsLabel2" >' + nam_wdir_from_deg + '</td>' +
       '</tr>' +
       alert_msg +
     '</table>';
     hmBoatInfoDiv.xOffset = 5;
     hmBoatInfoDiv.yOffset = 5;
     
     oBoat.oManager.kaMap.addObjectGeo(oBoat.oManager.pointCanvas,
                                       oBoat.aLocs[idx][0],
                                       oBoat.aLocs[idx][1],
                                       hmBoatInfoDiv);
    hmBoatInfoDiv.isVisible = true;
    
}

function hmBoat_hideInfo()
{
    if (hmBoatInfoDiv) {
      if (hmBoatInfoDiv.isVisible)
      {
          hmBoatInfoDiv.oManager.kaMap.removeObject( hmBoatInfoDiv);
          hmBoatInfoDiv.isVisible = false;
      }
    }
}
/************************************************************************/
/*                               hmColorClass                           */
/*                                                                      */
/*      Utility color class. 100 predefined colors available. One       */
/*      function is declared to get colors class.GetNextColor           */
/*      THIS IS NO LONGER USED IN THIS CAPACITY.  COLORS ARE ASSIGNED   */
/*      WHEN PULLING THE DATA FROM THE DB.
/************************************************************************/

function hmColorClass()
{
    this.aColors = new Array();
    
    this.mnCurrentColor = 0;
    this.mnMaxColors = 100;

    
}

function hmColorClassGetNextColor()
{
    szColor = this.aColors[this.mnCurrentColor];
    this.mnCurrentColor =  this.mnCurrentColor +1;
    if (this.mnCurrentColor == this.mnMaxColors)
    {
        this.mnCurrentColor = 0;
    }

    return szColor;
}

hmColorClass.prototype.GetNextColor = hmColorClassGetNextColor;



/************************************************************************/
/*             Utility function to add a boat to the boat list.         */
/************************************************************************/
function hmAddBoat(name, idx, loc, ts, spd, dir, class_id, 
  skipper_name, design, hail_port, distance_from_finishline_nm,
  nam_wspd_knots, nam_wdir_from_deg, rgb)
{
    var sel = document.forms[0].lease_areas_goto;
    var sq_str = '';
    var boat = name;
    sel.options[sel.options.length] = new Option(name+ ' '+sq_str,sel.options.length-1,false,false);
    rgb = rgb.replace(/ /g,',');
    myBoatManager.addBoat(new hmBoat(name, idx, loc, ts, spd, dir, class_id, rgb, sel.options.length-2, 
      skipper_name, design, hail_port, distance_from_finishline_nm, nam_wspd_knots, nam_wdir_from_deg));
}

function hmUpdateTimeSelector()
{
    var sel = document.forms[0].HMTimeSelector;
    sel.options.length = 0; //remove existing stuff
    var nCurrentTime = Number(myBoatManager.nStartTime); // select is off by 1

    var aMonthText = new Array();
    aMonthText[0] = 'Jan';
    aMonthText[1] = 'Feb';
    aMonthText[2] = 'Mar';
    aMonthText[3] = 'Apr';
    aMonthText[4] = 'May';
    aMonthText[5] = 'Jun';
    aMonthText[6] = 'Jul';
    aMonthText[7] = 'Aug';
    aMonthText[8] = 'Sep';
    aMonthText[9] = 'Oct';
    aMonthText[10] = 'Nov';
    aMonthText[11] = 'Dec';
    
    var d;
    var nMonth;
    var mm;
    var dd;
    var s = 0;
    
    while (nCurrentTime <=  myBoatManager.nEndTime)
    {
        d = new Date(nCurrentTime * 1000);
        
        mm = String(d.getUTCMonth()+1);
        mm = mm.replace(/(\b)(\d)\b/g, '$10$2');
        dd = String(d.getUTCDate());
        dd = dd.replace(/(\b)(\d)\b/g, '$10$2');
        hh = String(d.getUTCHours());
        hh = hh.replace(/(\b)(\d)\b/g, '$10$2');
        
        var sTimeString = d.getUTCFullYear()
          +"-"+mm
          +"-"+dd
          +" "+hh+":00 GMT";
        
        if (sTimeString == document.forms[0].time_stamp.value) {
          sel.options[sel.options.length] = 
            new Option(sTimeString, nCurrentTime, false, true);
          myBoatManager.nCurrentTime = s;
        }
        else {
          sel.options[sel.options.length] = 
            new Option(sTimeString, nCurrentTime, false, false);
          s++;
        }
    
        nCurrentTime = Number(nCurrentTime) + t_int;
    }

}

function hmProcessStartEndTime()
{
    myBoatManager.nStartTime = startDate.getTime() / 1000; // aStartEndTime[0];
    myBoatManager.nEndTime = endDate.getTime() / 1000; // aStartEndTime[1];
    
    hmUpdateTimeSelector();

    hmGetBoats();
}

function hmGetStartEndTime()
{
    //call('hmgetstartendtime.php?test=1', null, hmProcessStartEndTime );
    call('hmgetstartendtime.php', null, hmProcessStartEndTime );
}
/************************************************************************/
/*                                hmGetBoats                            */
/*                                                                      */
/*      Function calling the server to retreive boat infos for a        */
/*      certain time                                                    */
/************************************************************************/
function hmGetBoats()
{
  mm = new String(startDate.getUTCMonth()+1);
  mm = mm.replace(/(\b)(\d)\b/g, '$10$2');
  dd = new String(startDate.getUTCDate());
  dd = dd.replace(/(\b)(\d)\b/g, '$10$2');
  var s = startDate.getUTCFullYear()+'-'+mm+'-'+dd+' 00:00';

  mm = String(endDate.getUTCMonth()+1);
  mm = mm.replace(/(\b)(\d)\b/g, '$10$2');
  dd = String(endDate.getUTCDate());
  dd = dd.replace(/(\b)(\d)\b/g, '$10$2');
  var e = endDate.getUTCFullYear()+'-'+mm+'-'+dd+' 23:59';
        
  call( 'get_obs_cache.phtml?'
    +'t_min='+s
    +'&t_max='+e
    +'&t_int='+t_int
    +'&t_tol='+t_tol
    +'&session_id=', null, hmProcessBoats );
}

function hmCreatePointImage(rgb,boat)
{
    var width = 9;
    var height = 9;
    var sRGB = new String(rgb);
    var aRGB = sRGB.split(",");
    var sq_str = '';


    var loc = document.createElement('img');
//    loc.width = width;
//    loc.height = height;
    var hotspotImg = '/races/boat_markers/boat_' + sq_str + aRGB[0] + '_' + aRGB[1] + '_' + aRGB[2] + '.gif';

    loc.src = hotspotImg; // './images/expand.png'; // hotspotImg;
    loc.style.position = "absolute";
    loc.style.zIndex = 1;
    
    //loc.onclick = myShowInfo;
    //loc.style.cursor = 'help';
    
    loc.xOffset = -10;
    loc.yOffset = -10;
    
    return loc;

}


function hmTimeClicked(nCommand)
{
    if (nCommand == 0)
    {
        document.forms[0].HMTimeSelector.selectedIndex --;
    }
    else if (nCommand == 1)
    {
        document.forms[0].HMTimeSelector.selectedIndex ++;
    }

    nSelected = document.forms[0].HMTimeSelector.selectedIndex;
    myBoatManager.setTimeIndice(nSelected);
}
