/**
 * Satellite trace web-service
 * Author Denis Volkov (C) 2007-2009
 *
 * JavaScript functions
 *
 */


function SatTr()
{
  // Current images random
  var imgRnd = 0;

  // AJAX handler URL
  var ajaxURL;

  var CurrentTab = null;

  // Current time and last reload time
  var lastReloadTime = 0, lastTimestamp = 0;

  // Zoom on framesets tab
  var ZoomMax = 0, ZoomMin = ZoomCurrent = 3;
  var ZoomMode = '';
//  var ZoomCenter = '';
  var MapScrollPos = null;

  var MapType = 'ru';

  var MapViewFrame = null;
  var MapView = null;
  var ImageCache = null;

  var MainImageLoad = null;

  // Pixel to lat/lon calculation
  var Pixel2LatLon = {
    tracks_ru: [16.896114195083, 0.13798572561459, 82.656826568266, -0.07380073800738],
    tracks_world: [-182.842857, 0.2857142857, 93.957142857, -0.2857142857],
    scale0: [17.558935361217, 0.018377693282636, 83.741198, -0.010194],
    scale1: [17.338263257976, 0.036763152334671, 83.66966, -0.020387],
    scale2: [17.70583262891, 0.073541842772612, 84.326496, -0.040816],
    scale3: [17.41116751269, 0.14720812182741, 83.658545, -0.081301]
  };

  var afterImageLoad = null;

  // OnLoad handler
  this.onLoad = function()
  {
    var self = this;
    // Setup ajax subsystem
    ajaxURL = document.URL;
    $.ajaxSetup({
      url: document.URL,
      type: 'post',
      timeout: 30000,
      error: this.makeHandler(this.onAjaxError),
      success: this.makeHandler(this.onAjaxSuccess)
    });

    MapViewFrame = $('#map_view_frame')[0];

    var mouseMove = this.makeHandler(this.onMapMouseMove);
    var mouseDown = this.makeHandler(this.onMapMouseDown);
    MainImageLoad = this.makeHandler(this.onMainImageLoad);

    // Add tabs
    $('#control_panel').tabs({
//      fxAutoHeight: true,
      onShow: this.makeHandler(this.onTabSwitched)
    });

    // Show current date
    if (CurrentTab == 'cp_orbits' || CurrentTab == 'cp_region' )
    {
      $('#time_current')[0].checked = true;
      $('#time_set_date').val('');
    }

    // Add control handlers
    $('#sat_list input[type="checkbox"]').click(this.makeHandler(this.onSatelliteCheck));
    $('#frames_list input[type="checkbox"]').click(this.makeHandler(this.onFramesetCheck));
    $('#time_set').click(function(){ $('#time_set_date').focus(); });
    $('#time_set_reload').click(this.makeHandler(this.onCustomTimeReload));
    $('#region_calc').click(this.makeHandler(this.onRegionCalc));
    $('#options_panel input[type="checkbox"]').click(this.makeHandler(this.onOptionsCheck));
    $('#zoom_panel input').click(this.makeHandler(this.onZoomButtonClick));
    $('#map_type_form input').click(this.makeHandler(this.onMapTypeClick));

    // Start reload timer
    window.setInterval(this.makeHandler(this.onReloadTimer), 1000);

    // Update zoom panel
    this.updateZoomPanel();

    // Create content in frame
    var frameDoc = GetDocument(MapViewFrame);
    $('#map_view_frame').load(function(){
      MapView = frameDoc.getElementById('map_view');
      ImageCache = frameDoc.getElementById('img_cache');
      $( MapView ).mousemove(mouseMove).mousedown(mouseDown).html('Waiting...');
      self.onTabSwitched();
    });
    frameDoc.open();
    frameDoc.write('<'+'?xml version="1.0" encoding="UTF-8"?'+'><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
      + '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><html><head>'
      + '<style type="text/css"> body {margin: 0; padding: 0; } #img_cache { width: 1px; height: 1px; overflow: hidden; } </style>'
      + '</head><body><div id="map_view"></div><div id="img_cache"></div></body></html>');
    frameDoc.close();


  }

  // OnSatelliteCheck handler
  this.onSatelliteCheck = function()
  {
    // Get new state of checkboxes
    var checkedSatellites = [];
    $('#sat_list input[type="checkbox"]').each(function(){
      if(this.checked)
        checkedSatellites.push(this.value);
    });

    // Send post request
    $.ajax({
      data: {
        op: 'update',
        satellites: checkedSatellites.join(',')
      }
    });
  }

  // onFramesetCheck handler
  this.onFramesetCheck = function()
  {
    // Get new state of checkboxes
    var checkedFramesets = [];
    $('#frames_list input[type="checkbox"]').each(function(){
      if(this.checked)
        checkedFramesets.push(this.value);
    });

    // Send post request
    $.ajax({
      data: {
        op: 'update',
        framesets: checkedFramesets.join(',')
      }
    });
  }

  this.onOptionsCheck = function()
  {
    var options = {
      op: 'update'
    };
    $('#options_panel input[type="checkbox"]').each(function(){
        options[this.id] = (this.checked ? 1 : 0);
    });
    // Send post request
    $.ajax({
      data: options
    });
  }

  this.onZoomButtonClick = function(obj)
  {
    var zoomId = obj.id;
    if(ZoomMode != '')
    {
      $('#zoom_panel #' + ZoomMode).removeClass('pressed');
      $(MapView).css('cursor', 'default');
      if(ZoomMode == zoomId)
      {
        ZoomMode = '';
        return;
      }
    }
    if($('#zoom_panel #' + zoomId + '.disabled').size())
      return;
    ZoomMode = zoomId;
    $('#zoom_panel #' + ZoomMode).addClass('pressed');
    $(MapView).css('cursor', 'crosshair');
  }

  this.updateZoomPanel = function()
  {
    if(ZoomCurrent > ZoomMin)
      ZoomCurrent = ZoomMin;
    if(ZoomCurrent < ZoomMax)
      ZoomCurrent = ZoomMax;

    if(ZoomCurrent == ZoomMax)
      $('#zoom_in').addClass('disabled').attr('disabled', 'disabled');
    else
      $('#zoom_in').removeClass('disabled').removeAttr('disabled');
    if(ZoomCurrent == ZoomMin)
      $('#zoom_out').addClass('disabled').attr('disabled', 'disabled');
    else
      $('#zoom_out').removeClass('disabled').removeAttr('disabled');

    $('#cur_zoom').css('background-position', '0 ' + ((ZoomMin - ZoomCurrent) * -31) + 'px');
  }

  this.onMapMouseMove = function(obj, ev)
  {
    var event = ev[0];
    var x = event.offsetX || event.layerX;
    var y = event.offsetY || event.layerY;

    var transformId = 'tracks_ru';
    if(CurrentTab == 'cp_orbits')
      transformId = 'tracks_' + MapType;
    if(CurrentTab == 'cp_frames')
      transformId = 'scale' + ZoomCurrent;
    var transform = Pixel2LatLon[transformId];
    var lon = transform[0] + x * transform[1];
    lon = Math.round(lon * 100) / 100;
    if(lon > 180)
      lon = lon - 360;
    var lat = transform[2] + y * transform[3];
    lat = Math.round(lat * 100) / 100;
    var coords = '&nbsp;';
    if(lat >= -90 && lat <= 90 && lon >= -180 && lon <= 180)
      coords = Math.abs(lat) + '&deg;' + (lat >= 0 ? 'N ' : 'S ') + Math.abs(lon) + '&deg;' + (lon >= 0 ? 'E' : 'W');
    $('#coords_view').html(coords);
//    $('#pos_test').css('left', x + 'px').css('top', y + 'px').html('x=' + x + ', y=' + y);
  }

  this.onMapMouseDown = function(obj, ev)
  {
    var event = ev[0];
    var x = event.offsetX || event.layerX;
    var y = event.offsetY || event.layerY;
    if(ZoomMode == '')
      return;
    if(ZoomMode == 'zoom_in')
    {
      -- ZoomCurrent;
//      ZoomCenter = { x: x * 2, y: y * 2 };
      x *= 2;
      y *= 2;
    }
    else if(ZoomMode == 'zoom_out')
    {
      ++ ZoomCurrent;
//      ZoomCenter = { x: x / 2, y: y / 2 };
      x /= 2;
      y /= 2;
    }

    ZoomMode = '';
    $('#zoom_panel input').removeClass('pressed');
    this.updateZoomPanel();
    $(MapView).css('cursor', 'default');

    var vpWidth = MapViewFrame.clientWidth;
    var vpHeight = MapViewFrame.clientHeight;
    var offsetLeft = Math.max(Math.round(x - vpWidth / 2), 0);
    var offsetTop = Math.max(Math.round(y - vpHeight / 2), 0);
    MapScrollPos = { x: offsetLeft, y: offsetTop };

    $.ajax({
      data: { op: 'update', zoom: ZoomCurrent }
    });

//    $('#pos_test').css('left', x + 'px').css('top', y + 'px').html('x=' + x + ', y=' + y);
  }

  this.onMapTypeClick = function()
  {
    if($('#map_type_ru')[0].checked)
      MapType = 'ru';
    if($('#map_type_world')[0].checked)
      MapType = 'world';

    $.ajax({
      data: { op: 'update', map: MapType }
    });
  }

  this.onTabSwitched = function(obj, args)
  {
    CurrentTab = GetCurrentTab();
    this.reloadScene(true);
  }

  // Reload scene
  this.reloadScene = function(switchTab, forTime)
  {
    imgRnd = Math.round((1. + Math.random()) * 1e9);
    if(forTime == undefined)
      forTime = lastTimestamp;
    if(!forTime)
      forTime = Math.floor((new Date()).getTime() / 1000);

    // Replace content of map view area by scene image tiles
    if(CurrentTab == 'cp_frames')
    {
      $('#options_panel').hide();
    }
    else
    {
      $('#options_panel').show();
    }

    var imageUrl = 'getimg.php?x=0&y=0&rnd=' + imgRnd
      + '&ts=' + forTime
      + '&mode=' + CurrentTab;
//    imageUrl='img0/choose.gif';
    ImageCache.innerHTML = '<img src="' + imageUrl + '" border="0">';
    $('img', ImageCache).load(MainImageLoad);

    lastTimestamp = forTime;
  }

  // Prepare loaded map image, scroll if needed
  this.onMainImageLoad = function(obj)
  {
    $(MapView).empty().append(obj);

    // Position image after zoom
    if(MapScrollPos)
    {
      var wnd = MapViewFrame.contentWindow;
      wnd.scrollTo(MapScrollPos.x, MapScrollPos.y);
      MapScrollPos = null;
    }
  }

  // Reload timer handler
  this.onReloadTimer = function()
  {
    this.DoReloadTimer(0);
  }

  this.DoReloadTimer=function(force_refresh)
  {
    if (!$('#show_autorefresh')[0].checked && lastReloadTime!=0 && force_refresh!=1)
      return;

    // Set current time
    var now = new Date();
    var hour = now.getUTCHours(), min = now.getUTCMinutes(), sec = now.getUTCSeconds();
    var day = now.getUTCDate(), month = now.getUTCMonth() + 1, year = now.getUTCFullYear();
//    var hour = now.getHours(), min = now.getMinutes(), sec = now.getSeconds();
//    var day = now.getDate(), month = now.getMonth() + 1, year = now.getFullYear();
    var textDate = FormatDigit(day, 2) + '-' + FormatDigit(month, 2) + '-' + year
      + ' ' + FormatDigit(hour, 2) + ':' + FormatDigit(min, 2) + ':' + FormatDigit(sec, 2);
    $('#cur_time_display').html(textDate + ' GMT');
    if($('#time_set_date').val() == '')
      $('#time_set_date').val(textDate);

    // Reload scene, if needed
    var nowSec = Math.floor(now.getTime() / 1000);
    if((CurrentTab == 'cp_orbits' && $('#time_current')[0].checked && nowSec - lastReloadTime > 20)
      || force_refresh==1)
    {
      lastReloadTime = nowSec;
      this.reloadScene(false, nowSec);
    }

  }

  this.onCustomTimeReload = function()
  {
    // Parse time from input
    var customTime = $('#time_set_date').val();
    var parsed = customTime.match(/^\s*(\d{1,2}).(\d{1,2}).(\d{4})[^\d]+(\d{1,2}).(\d{1,2}).(\d{1,2})/);
    if(parsed != null)
    {
      if(!CheckDate(parsed[1], parsed[2], parsed[3]))
        alert('Введена несуществующая дата');
      else
      {
        var ts = Math.floor(Date.UTC(parsed[3], parsed[2]-1, parsed[1], parsed[4], parsed[5], parsed[6], 0) / 1000);
        if(!CheckTimeWithNow(ts))
          return;
        this.reloadScene(false, ts);
        lastReloadTime = 0;
      }
    }
    else
    {
      alert('Указано неверное время. Введите значение в формате DD-MM-YYYY HH:MM:SS');
    }
  }

  this.onRegionCalc = function()
  {
    // Parse and check input
    var lat1 = $('#region_lat1').val();
    var lat2 = $('#region_lat2').val();
    var lon1 = $('#region_lon1').val();
    var lon2 = $('#region_lon2').val();
    if(!lat1.length || !lat2.length || !lon1.length || !lon2.length)
    {
      alert('Необходимо ввести координаты области поиска');
      return;
    }
    var latMin = ParseCoord(lat1);
    var latMax = ParseCoord(lat2);
    var lonMin = ParseCoord(lon1);
    var lonMax = ParseCoord(lon2);
//    alert(latMin + ' ' + latMax + ' ' + lonMin + ' ' + lonMax);
    if(isNaN(latMin) || isNaN(latMax) || isNaN(lonMin) || isNaN(lonMax))
    {
      alert('Неверный формат введенных координат');
      return;
    }
    if(latMin < 40 || latMin > latMax || latMax > 90)
    {
      alert('Указаны недопустимые значения широты');
      return;
    }
    if(lonMin < 18 || lonMin > lonMax || lonMax > 180)
    {
      alert('Указаны недопустимые значения долготы');
      return;
    }

    var startTimeText = $('#region_time_since').val();
    var startTimeParts = startTimeText.match(/^\s*(\d{1,2}).(\d{1,2}).(\d{4})/);
    if(!startTimeParts)
    {
      alert('Указано некорректное значение даты');
      return;
    }
    if(!CheckDate(startTimeParts[1], startTimeParts[2], startTimeParts[3]))
    {
      alert('Введена несуществующая дата');
      return;
    }
    var startTime = Math.floor(Date.UTC(startTimeParts[3], startTimeParts[2]-1, startTimeParts[1], 0, 0, 0, 0) / 1000);
    if(!CheckTimeWithNow(startTime))
      return;

    var satId = $('#region_sat').val();
    if(!satId)
    {
      alert('Не выбран спутник');
      return;
    }

    // Send post request
    $.ajax({
      data: {
        op: 'search',
        satId: satId,
        latMin: latMin,
        latMax: latMax,
        lonMin: lonMin,
        lonMax: lonMax,
        startTime: startTime
      }
    });

  }

  // Success AJAX handler
  this.onAjaxSuccess = function(req, resp)
  {
    var doc = resp[0];
    var error = $('error', doc).text();
    if(error)
    {
      $('#region_result div').html('<p class="error">' + error + '</p>');
      alert(error);
    }
    else
    {
      $('#region_result p.error').remove();
      var findRes = $('find', doc).text();
//      alert(findRes);
      if(findRes)
        $('#region_result div').html('<p>' + findRes.replace(/\n/, '<br/>') + '</p>');
      this.reloadScene(false);
    }
  }

  // Error AJAX handler
  this.onAjaxError = function()
  {
    alert('Извините, произошла вычислительная ошибка. Обратитесь в отдел технической поддержки.');
  }

  // Create method call
  this.makeHandler = function(method)
  {
    var obj = this;
    return function() {
      return method.call(obj, this, arguments);
    };
  }

}

var satTr = new SatTr();
$(function() {
  satTr.onLoad();
});

function FormatDigit(num, length)
{
  var str = new String(num);
  while(str.length < length)
    str = '0' + str;
  return str;
}

function CheckDate(day, month, year)
{
  if(year < 1980 || year > 2030)
    return false;
  var date = new Date(Date.UTC(year, month-1, day, 12, 0, 0, 0));
  return date.getUTCDate() == day && (date.getUTCMonth() + 1) == month;
}

function GetCurrentTab()
{
  var currentTab = $('#control_panel > div:not(.tabs-hide)');
  return currentTab[0] ? currentTab[0].id : null;
}

function CheckTimeWithNow(ts)
{
  if(Math.abs(ts - (new Date()).getTime() / 1000) > 8640000)
  {
    alert('Допустимый интервал дат до 100 суток от текущей');
    return false;
  }
  return true;
}

function GetDocument(iframe)
{
  return iframe.contentWindow.document;
}

function ParseCoord(str)
{
  var parts = str.match(/^([+-]?\d+)(?:[\.,](\d)\d*)?$/);
  if(parts)
  {
    return parseInt(parts[1]) + (parts[2] ? parseInt(parts[2]) / 10 : 0);
  }
  else
    return NaN;
}

