/*
 * Copyright (C) by Netcetera AG.
 * All rights reserved.
 *
 * The copyright to the computer program(s) herein is the property of
 * Netcetera AG, Switzerland.  The program(s) may be used and/or copied
 * only with the written permission of Netcetera AG or in accordance
 * with the terms and conditions stipulated in the agreement/contract
 * under which the program(s) have been supplied.
 *
 */

/**
 * Manages the configuration ui 
 */


ConfigUI = {
  REL_TRAMDROID_NETWORK_API_ROOT: "http://netcetera.biz/tramdroid/restapi/network",
  
  _initialized: false,
  _callback: null,
  
  _editing: false,
  
  _config: undefined,
  
  _serverUrl: undefined,
  
  selectedStationGroup: undefined,
  
  /**
   * Initialization method.
   */
  init: function() {
    //populate config panel with existing options parsed from the URL
    var me = this;
    if (this._config) {
      $('#config #numDepartures').empty().options(this.rangeArray(5, 26)).val(this._config.opts.numDepartures);
      
      // get selected station from url, and set selected station group and station in select boxes
      var stationUri = this._config.stationUrl + "/station_group";
      var me = this;
      $.ajax({
        type: "GET",
        url: stationUri + "?callback=?",
        dataType: "json",
        success: function(data) {
          if (data) {
            me.selectedStationGroup = wemlinFrontendContext + data.station_group;
          };
        }
      });
      
    } else {
      $('#config #numDepartures').empty().options(this.rangeArray(5, 26)).val(5);
    }
  
    // first get the server URL for the next requests that will be made
    // the URL is acquired with JSONP from the server dispatcher(the current server for now)
    // if the server dispatcher is on another server this url should be changed to something like
    // http://server-dispatcher/wemlin-server-frontend/wemlin/serverUrl?callback=?
    $.ajax({
        type: "GET",
        url: wemlinFrontendContext + "/serverUrl?callback=?",
        dataType: "json",
        success: function(data) {
          if (data) {
            _serverUrl = data.serverUrl;

            // all the data on the starting page that depends on serverUrl is requested
            // here, because first the serverUrl should be obtained first, 
            // so everything can be done asynchronously
            // get station groups
            $('#config select#city').options({
              url: _serverUrl + ConfigUI.apiURL('station_groups'),
              resultMapper: function(result) {
                return $.map(result.station_groups, 
                    function(s) { 
                      return [[s['name'], wemlinFrontendContext + s['href'], s]] 
                    }
                );
              },
              // if a station was previously selected set the corresponding station group as selected 
              selected: (me.selectedStationGroup ? me.selectedStationGroup : "/station_groups/zh")
            });
            
            // get version
            $.ajax({
              type: "GET",
              url: _serverUrl + wemlinFrontendContext + "/version?callback=?",
              dataType: "json",
              success: function(data) {
                if (data) {
                  $('#config .version span').text(data.version.version);
                };
              }
            });
            
          };
        }
    });
    
    $('#config select#station').options({
      url: function() {
        if ($('#config select#city').val()) {
          // we don't need wemlinFrontendContext here. It is already in the value of the select options.
          return _serverUrl + ConfigUI.withFromTime($('#config select#city').val());
        } else {
          return null;
        }
      },
      resultMapper: function(result) {
        return $.map(result.stations, function(s) {
          return [[s['name'], wemlinFrontendContext + s['href'], s]]
        });
      },
      // if a station was already selected, display that station as 
      // selected when the config panel is displayed
      selected: (me._config ? me._config.stationUrl : "/stations/zypr")
      
    }).dependsOn('#config select#city');
    
    // FIXME var: uncomment when edge data is available
//    $('#config select#edge').options({
//      url: function() { 
//        var d = $('#config select#station').options('selected-data');
//        if (d) {
//          if (d.edges) {
//            return ConfigUI.withFromTime(d.edges.href);
//          }
//        } else {
//          return null;
//        }
//      },
//      
//      resultMapper: {key: 'href', label: 'name'},
//      prepend: ['Alle', "ALL"]
//      
//    }).dependsOn('#config select#station');
    
    $('#config #numDepartures,#config select#edge,#config select#city,#config select#station')
      .change(this.updateUrl);
      
    var drawertext = $('#config .drawer a').text();
    $('#config .drawer a').empty();
    $('#config .drawer a').text(drawertext);    
    
    $('#config form').submit(function() {
      ConfigUI.reconfigure();
      return false;
    });

    $('#cancelButton').click(function() {
      ConfigUI.hide();
      ConfigUI._editing = false;
      return false;
    });
    
    this.adjustLabels();
    
    this._initialized = true;
  },
  
  /**
   * Adjust the schedule table labels and the copyright box.
   */
  adjustLabels: function() {
    // fix sizes of schedule table label and copyright box
    $("#main").height($('body').height() * 0.81 - 1);
    $("#footer").height($('body').height() * 0.1 + 1);
    $("#schedule .line-icon").width(this.cellHeight());
    $("#schedule .labels td").height(this.cellHeight() / 2);
    $("#schedule .labels tr td").css("font-size", (this.cellHeight() / 2) * 3/4);
    $("#schedule tr td").css("border-bottom-width", Math.ceil(this.cellHeight() / 80));
    $("#copyright-box").css("top", ($("#footer").height() - (this.cellHeight()/5)) / 2); 
    $("#copyright-box").css("font-size", this.cellHeight() / 5);
  },
  
  /**
   * Method taken from Display.js for calculating table labels height when the table is blank.
   */ 
  cellHeight: function() {
    // if there are no departures (empty list), set the default size as there were 5 departures
    if (jQuery.browser.mozilla == true) {
      return Math.ceil($("#main").height() / (5 + 0.5));
    } 
    
    return Math.ceil($("#main").height() / (5 + 0.5) * 39/40); //<-- the "39/40" coefficient is to compensate for the border for the other browsers
  },
  
  /**
   * Setup actions for the options panel and the header.
   * 
   * The 'options panel' is the div element, with id='options',
   * that contains the dropdown boxes for selecting the: city, station and number of departures.
   * (the element with: Ortschaft, haltestelle, Sichtbare Anzahl Abfahrten, Version, ...).
   * 
   * 
   * 
   */
  setup: function() {
    //return;
    
    // hide the config panel and move up (set the top attribute to -height)
    $('#config')
      .css('visibility', 'hidden')
      .css('top', - $('#config').height());
    
    // What to do when the mouse hover in and out of the header.
    $('#header').hover(
      this.showTab, 
      function(ev) {
        if (ConfigUI._editing) {
          return;
        }
        
        var cfg = $(ev.relatedTarget).closest('#config');
        if (!cfg || cfg.size() == 0) {
          ConfigUI.hide();
        }
      });
    
    $('#header').click(
        this.showTab, 
        function(ev) {
          if (ConfigUI._editing) {
            return;
          }
          
          var cfg = $(ev.relatedTarget).closest('#config');
          if (!cfg || cfg.size() == 0) {
            ConfigUI.hide();
          }
        });
    
    // onclick handler for the drawer.
    // if the drawer is clicked, show the entire configuration panel.
    $('#config .drawer a,#config .drawer span,#config .drawer')
      .click(function(e) { ConfigUI.show(); e.preventDefault(); });
  },
  
  /**
   * Slide the options panel in view.
   */
  showTab: function() {
    $('#config .drawer a')
      .attr('href', window.location.href); 
      
    if ($('#config:animated').size() == 0) {
      $('#config')
        .css('visibility', 'visible')
        .animate({
          top: - $('#config').height() + $('#config .drawer').height() + 30
        }, "normal", "swing");

        $('#config').stopTime("hider");        
        $('#config').oneTime(3000, "hider", function() {
          ConfigUI.hide();
        });
    } 
  },
  
  /**
   * Hide the options pane with sliding effect.
   */
  hide: function(ev) {
    if ($('#config:animated').size() == 0) {
      $('#config')
        .animate({
          top: - $('#config').height()
        }, "normal", "swing", function() { $('#config').css('visibility', 'hidden') });    
    } 
  },
  
  /**
   * Adjust the panel height.
   */
  adjust: function() {
    if (!this._editing) {
      var c = $('#config');
      c.css('top', - c.height());
    }
    
    if (!this._config) {
      this.adjustLabels();
    }
  },

  /**
   * Set the config object.
   * 
   * @param config config object to set.
   */
  currentConfig: function(config) {
    this._config = config;
  },
  
  /**
   * Show options panel.
   */
  show: function(config) {
    
    if (config) {
      this.currentConfig(config);
    }
    
    if (!this._initialized) {
      this.init();
    }
    
    $('#config').stopTime("hider");
         
    // populate
    this._editing = true;

    if ($('#config:animated').size() == 0) {
      $('#config')
        .css('visibility', 'visible')
        .animate({
          top: 0
        }, "normal", "swing");      
    }
  },
  
  /**
   * Not used.
   */
  populate: function() {
    if (this._config) {
      if (this._config.stationUrl) {
        
        var m = this._config.stationUrl.match(/(\d+)(\/e\/(\d+))?/);
        
        if (m) {
          $.getJSON(this.apiURL("station_groups", "find?station_id=" + m[1]),
            function(data) {
              if (data.length > 0) {
                $("#config select#city").val(data[0].href).trigger('change');
                
              }
            });
          }
          //$('#config select#station').val(m[1]);
      }
      
      if (this._config.opts) {
        $('#config #numDepartures').val(this._config.opts.numDepartures);
      }
    }
  },
  
  /**
   * Call the method for creating the hash, and set it in the browser window.
   */
  reconfigure: function() {
    var h = ConfigUI.composeHash();
    
    this._editing = false;
    
    if (h) {
      window.location.hash = h;
      this.hide();
    }
  },
  
  /**
   * Create URL and display it in the bottom of the config panel.
   */
  updateUrl: function() {
    var u = ConfigUI.composeURL();
    if (!u) {
      u = window.location.href;
    } 
    
    $('#config .drawer a')
      .attr('href', encodeURI(u)); 
  },

  /**
   * Create the hash string based on the selections on the page.
   */
  composeHash: function() {
    var station = $("#station").val();
    var edge = $("#edge").val();
    var numDepartures = parseInt($("#numDepartures").val());
    var ctime = ConfigUI._config && ConfigUI._config.opts ? ConfigUI._config.opts.ctime : undefined;
    
    // FIXME: this fails because the edges are missing in the model
    // uncomment when edges are available
//    var sUrl = edge == "ALL" ? station : edge;
    var sUrl = station;
    
    if (sUrl) {
      if (_serverUrl) {
        return "#" + _serverUrl + sUrl + 
        (numDepartures && !isNaN(numDepartures) ? ";numDepartures=" + numDepartures : "") +
        (ctime ? ";ctime=" + ctime.toISOString() : "")
      } else {
        return "#" + sUrl + 
          (numDepartures && !isNaN(numDepartures) ? ";numDepartures=" + numDepartures : "") +
          (ctime ? ";ctime=" + ctime.toISOString() : "")
      }
    }
    
    return undefined;
  },
  
  /**
   * Create the complete URL with the new hash string.
   */
  composeURL: function() {
    
    var prefix;
    if (window.location.hash.length > 0) {
      prefix = window.location.href.substring(0, 
        window.location.href.indexOf(window.location.hash));
    } else {
      prefix = window.location.href;
    }
    
    var hash = ConfigUI.composeHash();
    
    if (hash) {
      return prefix + hash;
    }
    
    return undefined;
    
  },
  
  /**
   * 
   */
  apiURL: function() {
    var subUrl;
    
    if (arguments.length > 0) {
      subUrl = $.makeArray(arguments).join('/');
    }
    
    return ConfigUI.withFromTime(wemlinFrontendContext +
      $("html>head>link[rel='" + this.REL_TRAMDROID_NETWORK_API_ROOT + "']").attr('href') +
      (subUrl ? ("/" + subUrl) : ""));
      
  },
  
  /**
   * Add "from" parameter in the URL representing a starting time.
   */
  withFromTime: function(url) {
    if (!url) {
      return undefined;
    }
    
    return url + (url.indexOf("?") >= 0 ? "&" : "?") + "from=" + DateTime.now().toISOString();
  },
  
  /**
   * Create array of consecutive integers for the number of departures list.
   */
  rangeArray: function(from, to) {
    var r = [];
    for (var i = from; i < to; i++) {
      r.push(["" + i, i]);
    }
    
    return r;
  }
}
