/**
 * TPageControl is a descendant of TTabSet
 * Implements a set of tabs and a panel to show their data.
 * TPageControl can obtain his content from server by supplying an URL
 *
 * If URL is set and cached data does not exist or has expired then
 * a server call is made to that URL passing the selected tab index in order
 * to get the tab content and store it into the internal data array.
 *
 * Expire handle content update frequency.
 * Set it to a value greater than 0 (in milliseconds) to update content
 * when it hits the expire time, or set it to 0 to prevent content update.
 *
 * If URL is not set, then the content for tabs must be predefined.
 * Tab contents are divs inside page container (see bellow).
 *
 * TPageControl is a container element (like a DIV) where the first element
 * is the tabset control (usually an UL) and the next one is the page container
 * element (usually a DIV). The page container is where every new page is created
 * Pages are divs, and are created by page control on every content request to
 * server or can be pre defined by the user
 * Pages are created once. Subsequents updates just change their inner content.
 *
 * Use tab.selected in css to define styles of selected tabs
 * Use tab.over in css to define styles of active tabs
 * Handle "newpage" to add styles or manage pages when they are created
 *
 * @param {String | Element} pagecontrol: container element in document
 * @param {Integer} selected: index of the initial selected tab
 */
var TPageControl = function(pagecontrol, selected) {
  this.url = null;                      // Page content supplier script
  this.pages = [];                      // Holds the last content retrieved for every tab index.
  this.expire = 0;                      // Set cache expire to update page content. Set it to 0 to avoid caching data or -1 to avoid updating.
  this.visible = -1;                    // Currently visible page. Selected its not allways the visible page (like while making a request)
  this.modalwin = new TModalWin();      // Create a modal win to put over the current visible page when requesting an update
  this.postvar = 'tabid';               // Variable name usend when posting request
  this.modalColor = '#000';

  this.pagecontrol = TDOM.getElement(pagecontrol);
  if (!this.pagecontrol) { return; }

  // Get the tabset and initialize it
  var ts = TDOM.firstChild(this.pagecontrol);
  TTabSet.call(this, ts, selected);
  this.visible = this.selected;

  // Get page container and every existing page
  this.page = TDOM.nextElement(this.tabset);
  var page = TDOM.firstChild(this.page);
  var count = 0;
  while (page) {
    this.pages.push({page:page, expire:-1});
    count == this.selected ? page.style.display = 'block' : page.style.display = 'none';
    page = TDOM.nextElement(page);
    count++;
  }

  if (count == 1 && this.selected != -1) {
    this.pages[0].page.style.display = 'block';
    this.visible = 0;
  }
}

TPageControl.inherits(TTabSet);
TPageControl.waitMessage = '<div style="color:#fff">Actualizando<br />Por favor espere...</div>';

/**
 * Override select method to change page content
 * on tab change.
 *
 * @param {Integer | Element} tab: tab index or tab itself
 */
TPageControl.prototype.select = function (tab) {
  var selected = this.selected;
  TTabSet.prototype.select.call(this, tab);
  // If selected changed
  if (selected != this.selected) {
    // Send Update
    selected = this.pages[this.selected] || {};
    var visible = this.pages[this.visible];
    if (this.updateCurrent()) { return; }
    this.modalwin.close();

    // If no update, hide visible page
    if (visible && visible.page) {
      visible.page.style.display = 'none';
    }
    // And show selected one
    if (selected.page) {
      selected.page.style.display = 'block';
      this.visible = this.selected;
    }
  }
}

/**
 * THttp call to update current selected tab content
 * @param {TEvent} e: event
 */
TPageControl.prototype.updateCurrent = function() {
  var now = new Date();
  var ticks = now.getTime();
  var visible = this.pages[this.visible];
  var selected = this.pages[this.selected] || {};
  // If page update is needed
  if (this.url && selected.expire != 0 ) {
    if (selected.expire == undefined || selected.expire < ticks) {
      this.modalwin.color = this.modalColor;
      this.modalwin.modal = visible && visible.page ? visible.page : this.pagecontrol;
      this.modalwin.show(TPageControl.waitMessage);
      var http = new THttp;
      http.show = this.selected;
      http.addParam(this.postvar, this.selected);
      http.addEventListener("complete", this.doHttpComplete, this);
      http.addEventListener("ready", http.free, http);
      http.post(this.url);
      return true;
    }
  }
}

/**
 * THttp callback method
 * @param {TEvent} e: event
 */
TPageControl.prototype.doHttpComplete = function(e) {
  var http = e.target;
  if (http.error) {
    this.modalwin.show('<div style="color:#fff">'+http.lastError+'</div>');
  } else {
    var selected = this.pages[http.show] || {};
    if (!selected.page) {
      selected.page = document.createElement('div');
      selected.page.style.display = 'none';
      this.page.appendChild(selected.page);
      this.dispatch("newpage", selected.page);
    }
    var now = new Date();
    var ticks = now.getTime();
    var response = {show:http.show,text:http.toString()};
    this.dispatch("beforeupdate", response);
    selected.page.innerHTML = response.text;
    selected.expire = ticks + this.expire;
    this.pages[http.show] = selected;
    // Show selected page
    if (http.show == this.selected) {
      this.modalwin.close();
      // If no update, hide visible page
      var visible = this.pages[this.visible];
      if (visible && visible.page) {
        visible.page.style.display = 'none';
      }
      // And show selected one
      selected.page.style.display = 'block';
      this.visible = this.selected;
    }
  }
}
