// TODO: hide the scope a bit ...
// GLOBAL VARS
var g_sSportId;       // declared here but defined elsewhere
var g_sBaseLocation; // declared here but defined elsewhere

var g_xmlDocTables = []; // contains all of the XML doc/tables

/** static variables for the state machine */
function state() {}
// state machine
state.READY = 0; // state READY is a combination of NO states
state.STYLESHEET_LOADED = 1; // 2^0
state.XML_LOADED = 4;         // 2^2
// NB. each (new) state should be a power of 2 (ie. any state combination can be
// identified IF keeping to this mechanism)

// state.LOADED is a combination of states:
state.LOADED = state.STYLESHEET_LOADED + state.XML_LOADED;
/** end state */

/**
 * Constructor for the XMLDocTable
 * @author Rebecca Evans <rebecca.evans@championdata.com.au>
 * @version 0.1
 * $Id: sarissa_buildTable.js,v 1.21 2010/02/26 03:39:48 adrianprigg Exp $
 * @param  URI - the URI of the xml doc
 * @param  divTableId - the Id of the <div> target for the table
 * @param  tableId - the Id of the table - used by the stylesheet
 * @param  params - params used by the stylesheet (name value pairs)
 *
 *       buildTable.xsl
 *         + tableId - the Id of the table
 *         + sortableCols - a list of cols to be sorted on (white-space separated)
 *         + sortColumn - the column to be sorted on
 *         + data-type - (text | numeric)
 *         + sortOrder - (ascending | descending)
 *         + searchStr - the search string
 *         + currentPage - the current page we are on
 *         + split - the delimiter for chattel (firstname#lastname): Default=[#]
 *         + uSquadId - the users squad Id (used by Standings and League Standings)
 *         + findUSquad - related to find me button on Standings page (true | false)
 *         + round - the round being played (used by League Results table)
 *       buildRbRTable.xsl
 *         + sportId - g_sSportId
 *         + baseLocation - g_sBaseLocation
 *       buildCalDefault.xsl
 *         + tableId
 *         + baseLocation
 *
 * @param  xslURI is OPTIONAL: it is the stylesheet to use for this table.
 *   (default is buildTable.xsl)
 */
function XMLDocTable (URI, divTableId, tableId, params, xslURI) {
  this.state = state.READY;
  this.divTable = divTableId;
  this.paramSet = [];

  /* public instance methods priviledged at the class level */
  /* privileged members to set parameters */
  this.setParameter = function (name, value) {
    if (value == undefined) { value = ""; }
    this.paramSet[name] = value;
  };

  this.setParameters = function (params) {
    if (params != undefined ) {
      for (var name in params) {
        this.setParameter(name, params[name]);
      }
    }
  };
  this.getParameters = function () { return this.paramSet; }
  this.getParameter = function(name) { return this.paramSet[name]; }

  this.setParameters(params);
  this.setParameter("tableId", tableId);
  this.getState = function() { return this.state; }
  this.setStylesheet(xslURI);
  this.setXML(URI);
}
/* END CONSTRUCTOR */

/**
 * Utility function to get XML Document (async = false)
 * @author $author$ <rebecca.evans@championdata.com.au>
 * @version $revision$
 * $Id: sarissa_buildTable.js,v 1.21 2010/02/26 03:39:48 adrianprigg Exp $
 * returns the XMLDoc
 * Can throw exception if:
 *  1. URI not found
 *  2. xmlDoc is not valid xml
 */
function getXMLDoc(URI) {
  var xmlHttp = new XMLHttpRequest();
  xmlHttp.open ("GET", URI, false);
  xmlHttp.send(null);

  /* force request in IE (versions before 7) - this is an IE bug!!
   * @see http://en.wikipedia.org/wiki/XMLHttpRequest#Caching
   */
  if(!xmlHttp.getResponseHeader("Date"))
  {
    var cached = xmlHttp;
    xmlHttp =  new XMLHttpRequest();
    var ifModifiedSince = cached.getResponseHeader("Last-Modified");
    ifModifiedSince = (ifModifiedSince) ?
        ifModifiedSince : new Date(0); // January 1, 1970
    xmlHttp.open("GET", URI, false);
    xmlHttp.setRequestHeader("If-Modified-Since", ifModifiedSince);
    xmlHttp.send(null);
    if(xmlHttp.status == 304)
    {
      xmlHttp = cached;
    }
  }
  /* end of IE bug fix */

  var xmlDoc;
  xmlDoc = xmlHttp.responseXML;
  xmlDoc.async = false;

  return xmlDoc;
};

/**
 * Utility function to get XML Document (async = TRUE)
 * @author $author$ <rebecca.evans@championdata.com.au>
 * @version $revision$
 * $Id: sarissa_buildTable.js,v 1.21 2010/02/26 03:39:48 adrianprigg Exp $
 * @param URI
 * @param callback - the callback function once the document is loaded
 * Can throw exception if:
 *  1. URI not found
 */
function getXML(URI, callback) {
  var xmlhttp = new XMLHttpRequest();
  xmlhttp.open("GET", URI, true);
  xmlhttp.onreadstatechange = function() {
    if (xmlhttp.readyState == 4) {
      callback(xmlhttp);
    }
  };
  xmlhttp.send(null);
}

/**
 * These templates are provided, such that if anything is needed to be done
 * when these state changes occur - the functions can be overridden.  This is
 * for extensibility!
 * Override if necessary.
 * - currently ChattelResearch.js overrides onXMLLoadedStateChange.
 */
XMLDocTable.prototype.onXMLLoadedStateChange = function() { /* empty fn */ };
XMLDocTable.prototype.onXSLLoadedStateChange = function() { /* empty fn */ };
XMLDocTable.prototype.onUpdateTable = function() { /* empty fn */ };
XMLDocTable.prototype.onUpdateTablePage = function() { /* empty fn */ };
XMLDocTable.prototype.onSortTable = function() { /* empty fn */ };
XMLDocTable.prototype.onSearchTable = function() { /* empty fn */ };
XMLDocTable.prototype.onLoadTable = function() { /* empty fn */ };

XMLDocTable.prototype.changeState = function(statechange) {
  this.state = this.state + statechange;
  if (statechange == state.XML_LOADED) {
    this.onXMLLoadedStateChange();
  } else if (statechange == state.XSL_LOADED) {
    this.onXSLLoadedStateChange();
  }
  if (this.state == state.LOADED) {
    // do not load the nielsen stats on first load of the table (false)
    this.updateTable(false);
    this.onLoadTable();
  }
};

/**
 * can throw exception!
 */
XMLDocTable.prototype.loadStylesheet = function (xmlhttp) {
  this.xsl = xmlhttp.responseXML;
  try {
    this.processor.importStylesheet(this.xsl);
    this.changeState(state.STYLESHEET_LOADED);
  }
  catch (e) {
    // this error will occur if the stylesheet is not well-formed XML or invalid
    document.getElementById(this.divTable).innerHTML = "<b>An error has occurred.  Please try again shortly. " + "Failed to import stylesheet. " + e.message + "</b>"; // for debugging purposes including full error.
  }
};

XMLDocTable.prototype.setStylesheet = function (URI) {
  var _this = this;
  var defaultURI = g_sBaseLocation + "/xmldata/buildTable.xsl";
  if (URI == undefined) { URI = defaultURI; }
  this.processor = new XSLTProcessor();
  var xmlhttp = new XMLHttpRequest();
  xmlhttp.open("GET", URI, true);
  xmlhttp.onreadystatechange = function() {
    if (xmlhttp.readyState == 4) {
      _this.loadStylesheet(xmlhttp);
    }
  };
  xmlhttp.send(null);
};

XMLDocTable.prototype.loadXML = function (xmlhttp) {
  this.xml = xmlhttp.responseXML;
  this.changeState(state.XML_LOADED);
};

XMLDocTable.prototype.setXML = function (URI) {
  // if the XML is already defined, then we need to
  // change states to unload the current XML, and load
  // the new XML
  if (this.getXML()) {
    this.changeState(-(state.XML_LOADED)); // set the state to unload.
  }
  var _this = this;
  var xmlhttp = new XMLHttpRequest();
  xmlhttp.open("GET", URI, true);
  xmlhttp.onreadystatechange = function() {
    if (xmlhttp.readyState == 4) {
      _this.loadXML(xmlhttp);
    }
  };
  xmlhttp.send(null);
};

XMLDocTable.prototype.getXML = function () {
  return this.xml; // could be undefined IF document not yet loaded
};

XMLDocTable.prototype.updateTable = function(reload) {
  // default behaviour is to reload the Nielsen stat ratings
  // the exception being - when the table is loaded for the first time
  // as it will be loaded on page load.
  if (reload == undefined) { reload = true; }
  try {
    this.processor.clearParameters();

    for (var name in this.paramSet)
    {
      this.processor.setParameter(null, name, this.paramSet[name]);
    }
    Sarissa.updateContentFromNode(this.xml, document.getElementById(this.divTable), this.processor);
    this.onUpdateTable();
    if (reload)
    {
      // needed for Nielsen stat ratings
      if (this.reloadPageBaseline != undefined) { reloadPageBaseline(); }
    }
  }
  catch (e)
  {
    if (document.getElementById(this.divTable) != null)
    {
      document.getElementById(this.divTable).innerHTML = "<b>An error has occurred.  Please try again shortly. " + e.message + "</b>"; // for debugging purposes including full error.
    }
  }
};

XMLDocTable.prototype.updateTablePage = function(page) {
  this.setParameter("currentPage", page);

  this.onUpdateTablePage();
  this.updateTable();
};

XMLDocTable.prototype.sortTable = function(sortColumn, datatype, sortOrder) {
  this.setParameter("currentPage", 1); // reset current page when sorting
  this.setParameter("sortColumn", sortColumn);
  this.setParameter("data-type", datatype);
  this.setParameter("sortOrder", sortOrder);
  this.onSortTable();
  this.updateTable();
};

XMLDocTable.prototype.searchTable = function(searchStr) {
  this.setParameter("searchStr", searchStr);
  this.setParameter("currentPage", 1); // reset the current page to first page
  this.onSearchTable();
  this.updateTable();
};

// PUBLIC methods
function loadTable (URI, divId, tableId, params, xslURI) {
  if (xslURI == undefined) {
    g_xmlDocTables[tableId] = new XMLDocTable(URI, divId, tableId, params);
  }
  else {
    g_xmlDocTables[tableId] = new XMLDocTable(URI, divId, tableId, params, xslURI);
  }
}

function loadRbRTable (URI, divId, tableId, params) {
  var xslURI = g_sBaseLocation + "/xmldata/buildRbRTable.xsl";
  g_xmlDocTables[tableId] = new XMLDocTable(URI, divId, tableId, params, xslURI);
}

function loadFinalsTable(URI, divId, tableId, params) {
  var xslURI = g_sBaseLocation + "/xmldata/buildFinalsTable.xsl";
  g_xmlDocTables[tableId] = new XMLDocTable(URI, divId, tableId, params, xslURI);
}

/* params is optional */
function updateTable (tableId, params) {
  if (params != undefined)
  {
    g_xmlDocTables[tableId].setParameters(params);
  }
  if (tableId == undefined) {
    throw "TableId not defined.";
  }
  g_xmlDocTables[tableId].updateTable();
}

function updateTablePage (tableId, page) {
  g_xmlDocTables[tableId].updateTablePage(page);
}

function searchTable (tableId, searchStr) {
  g_xmlDocTables[tableId].searchTable(searchStr);
}

function setTableParameter (tableId, name, value) {
  g_xmlDocTables[tableId].setParameter(name, value);
}

function setTableParameters (tableId, params) {
  g_xmlDocTables[tableId].setParameters(params);
}

function sortTableSarissa (tableId, sortColumn, datatype, sortOrder) {
  g_xmlDocTables[tableId].sortTable(sortColumn, datatype, sortOrder);
}
