/**
 *  object to control one or more WATTableView objects as e.g. fill tables with data from an XML
 *  structure that has been received for an AJAX request
 *
 *  @author   Tobias Hettinger
 *  @version  $Id: tablecontrol.js,v 1.23 2009/05/25 14:12:31 tobias Exp $
 */
 
 
/**
 *  constructor
 */
var WATTableControl = function(name)
{
  //  set the member variables
  this.name = name;
  this.tableViews = new Array();
}


//=====================================================================================================================
//  user interface
//=====================================================================================================================

/**
 *  function to add the passed WATTableView object to the internal list of table views
 */
WATTableControl.prototype.AddTableView = function(name, watTableView, ajaxHandler, modulePrefix)
{
  //  create the table view entry
  var tableView = new Array();
  tableView['tableView'] = watTableView;
  tableView['ajaxHandler'] = ajaxHandler;
  tableView['modulePrefix'] = modulePrefix;

  //  add the passed table view to the table view array of the table control
  this.tableViews[name] = tableView;
}

/**
 *  function to get the ajax handler for the table with the passed name
 *
 *  @param string name  name of the table
 *
 *  @return string  the function returns the ajax handler for the selected table or null
 *                  if the ajax handler is not available
 */
WATTableControl.prototype.GetAjaxHandler = function(name)
{
  if (this.tableViews[name]) return this.tableViews[name]['ajaxHandler'];
    else return null;
}

/**
 *  function to get the module prefix for the table with the passed name
 *
 *  @param string name  name of the table
 *
 *  @return string  the function returns the module prefix for the selected table or null
 *                  if no module prefix is available
 */
WATTableControl.prototype.GetModulePrefix = function(name)
{
  if (this.tableViews[name]) return this.tableViews[name]['modulePrefix'];
    else return null;
}

/**
 *  structure of the expected XML
 *
 *  <cv  :=> convert a static table into a dynamic one
 *    n="[name of the dynamic table]" id="[id of the static table]" nid="[id of the navigation bar (if required)"
 *    iop="[number of items on one page (only if required)]" />
 *
 *  <t   :=> select a new table
 *    n="[name of the table in the TableControl class (the one that has been passed in the AttTableView function]">
 *
 *    <cl />   :=> clear the selected table (including the data structure)
 *    <st />   :=> (re)show the table
 *    <sr />   :=> (re)show the rows (without refreshing the columns)
 *    <sf />   :=> save the current filter
 *    <rf />   :=> restore the saved filter values
 *    <sort c="[name of the column to sort or NULL if the current sort column should be used]"
 *          d="[1 for 'desc' or 0 for 'asc'] />
 *
 *    <cs>   :=> block of column definitions
 *      <c   :=> definition of a single column
 *         n="[name of the column, required]"   :=> name of the column
 *         s="[1/0, 0 if not defined]"          :=> 1 if the column is sortable
 *         fi="[1/0, 0 if not defined]"         :=> 1 if a filter input should be shown
 *         w="[width]">                         :=> width of the column in pixels (only if a fixed width is required)
 *
 *      [caption of the column]
 *
 *      </c>
 *    </cs>
 *
 *    <r k="[key of the row (e.g. the row id in the database)]"   :=> a single row definition
 *       d1="[optional data]" d2="[optional data]" d3="[optional data]">
 *      <f n="[name of the field which corresponds to the name of its column]">
 *        <v t="[s/n  :=> data type of the value whereas the data type of the sortable value overwrites this data type]">
 *          [value to show]</v>   :=> if the value tag is not sent, the value is set to 'null'
 *        <s t="[s/n  :=> data type of the value]">
 *          [sortable value]</s>  :=> if the value contains e.g. HTML or a date string, the sortable value
 *                                    can be sent to provide the possibility to sort the value even if the
 *                                    value itself can not be easily sorted. If this value is not sent, the
 *                                    value itself is sorted
 *      </f>
 *    </r>
 *
 *  </t>
 */
WATTableControl.prototype.ParseXML = function(xml, suppressErrors)
{
  //  get the response or error elements
  var node = xml.firstChild;
  while(node)
  {
    switch(node.nodeName)
    {
      //  convert a static table in a dynamic one
      case 'cv' :
        //  get the configuration
        var tableId = node.getAttribute('id');
        var navId = node.getAttribute('nid');
        var tableName = node.getAttribute('n');
        var itemsOnPage = node.getAttribute('iop');
        var selectMode = node.getAttribute('s');
        var rowKey = node.getAttribute('r');
        if (!navId || !itemsOnPage) itemsOnPage = -1;

        //  a table can be converted if the id and the name of the table is available
        if (tableId && tableName)
        {
          //  convert the table
          var tableView = new WATTableView(this.name + ".tableViews['" + tableName + "']['tableView']",
                                           tableId, itemsOnPage, navId);
          this.AddTableView(tableName, tableView, null, null);
          if (selectMode != null) tableView.selectMode = selectMode;
          var tableConverter = new WATTableConverter(tableView);
          tableConverter.Convert();
          
          //  show the page that contains the selected row
          if (rowKey) tableView.SetPageByRowKey(rowKey, true);
        }
        break;
    
      //  data has been sent
      case 't' :
        //  get the name of the table and load the selected TableView object
        var tableName = node.getAttribute('n');
        if (tableName && this.tableViews[tableName] && this.tableViews[tableName]['tableView'])
        {
          //  get the selected table view
          var tableView = this.tableViews[tableName]['tableView'];
      
          //  parse the table data
          var table = node.firstChild;
          while(table)
          {
            switch(table.nodeName)
            {
              //  a clear table signal has been sent
              case 'cl' :
                //  clear the table and the underlying data structure
                tableView.ClearTable();
                break;
                
              //  (re)show the table
              case 'st' :
                //  show the table
                tableView.ShowTable();
                break;
                
              //  save the current filter
              case 'sf' :
                //  save the filter values
                tableView.SaveFilter();
                break;
                
              //  restore the saved filter values
              case 'rf' :
                //  restore the filter
                tableView.RestoreFilter();
                break;
                
              //  sort the table
              case 'sort' :
                //  get the parameters
                var columnName = table.getAttribute('c') ? table.getAttribute('c') : tableView.sortColumnName;
                var desc = table.getAttribute('d') ? (table.getAttribute('d') == 1 ? true : false) : tableView.sortDesc;
                tableView.Sort(columnName, desc);
                tableView.SortGroups();
                break;
          
              //  scroll to the row with the selected key
              case 'sr' :
                var key = table.getAttribute('key');
                if (key)
                {
                  //  get the selected row
                  var row = tableView.GetRow(key);
                  if (row && row.tr)
                  {
                    //  get the position of the row
                    var pos = watGetTopPos(row.tr);
                    
                    //  ... not yet ...
                  }
                }
                break;
                
              //  a set of columns was sent
              case 'cs' :
                //  parse the columns
                var column = table.firstChild;
                while(column)
                {
                  switch(column.nodeName)
                  {
                    //  a column definition was sent 
                    case 'c' :
                      //  get the column attributes
                      var columnName = column.getAttribute('n');
                      //  the column name is required
                      if (columnName)
                      {
                        //  get the optional attributes
                        var sortable = column.getAttribute('s');
                        var verticalText = column.getAttribute('vt');
                        var filterInput = column.getAttribute('fi');
                        var filterInputNewLine = column.getAttribute('finl');
                        var defaultFilterValue = column.getAttribute('dfi');    
                        var width = column.getAttribute('w');
                        
                        //  create the caption
                        var caption = (column.firstChild) ? column.firstChild.data : columnName;
                      
                        //  create a new column object
                        var tableColumn = new WATTableColumn(watDivDecode(caption),
                                                            (sortable && sortable == '1') ? true : false,
                                                            (filterInput && filterInput == '1') ? true : false);
                        //  set the properties
                        if (verticalText && verticalText == '1') tableColumn.verticalText = true;
                        if (width) tableColumn.width = width;
                        if (defaultFilterValue) tableColumn.filterString = defaultFilterValue;
                        if (filterInputNewLine == '1') tableColumn.filterInputNewLine = true;
                        
                        //  get additional column data
                        var columnNode = column.firstChild;
                        while(columnNode)
                        {
                          switch(columnNode.nodeName)
                          {
                            //  a filter value has been sent
                            case 'fv' :
                              var filterValue = columnNode.getAttribute('v');
                              var filterCaption = (columnNode.firstChild) ? columnNode.firstChild.data : null;
                              if (filterValue && filterCaption)
                                tableColumn.filterValues[filterValue] = filterCaption;
                              break;
                          }
                        
                          columnNode = columnNode.nextSibling;
                        }
                        
                        //  add the column to the table
                        tableView.AddColumn(columnName, tableColumn);
                      }
                      break;
                  }
              
                  //  try to parse the next column
                  column = column.nextSibling;
                }
                break;
              
              //  a group was sent
              case 'g' :
                var groupName = table.getAttribute('n');
                var key = table.getAttribute('key');
                var order = table.getAttribute('o');
                var caption = (table.firstChild) ? table.firstChild.data : null;
                if (groupName && key && caption)
                {
                  var group = new WATTableGroup(key, watDivDecode(caption));
                  tableView.AddGroup(groupName, group);
                  if (order) group.order = order;
                }
                break;
              
              //  a row was sent
              case 'r' :
                //  initialize the row
                var cells = new Array();
                var row = table.firstChild;
                
                //  get the row attributes
                var key = table.getAttribute('key');
                var groups = table.getAttribute('g');
                var d1 = table.getAttribute('d1');
                var d2 = table.getAttribute('d2');
                var d3 = table.getAttribute('d3');
                var replace = table.getAttribute('r') ? true : false;
                var autoSelect = table.getAttribute('as') ? true : false;
                var href = table.getAttribute('href');
                if (href) href = watDivDecode(href);
                
                //  parse the row
                while(row)
                {
                  switch(row.nodeName)
                  {
                    //  a field definition has been sent
                    case 'f' :
                      //  get the name of the field (required attribute)
                      var fieldName = row.getAttribute('n');
                      if (fieldName)
                      {
                        //  get the field data
                        var fieldValue = null;
                        var valueDataType = 's';
                        var filterValue = null;
                        var sortableValue = null;
                        var sortableDataType = 's';
                        var field = row.firstChild;
                        while(field)
                        {                        
                          switch(field.nodeName)
                          {
                            //  the value of the field has been sent
                            case 'v' :
                              //  get the attributes
                              valueDataType = field.getAttribute('t');
                              //  get the data
                              if (field.firstChild) fieldValue = field.firstChild.data;
                              break;
                            
                            //  an optional filter value has been sent
                            case 'fv' :
                              //  get the data
                              if (field.firstChild) filterValue = field.firstChild.data;
                              break;
                            
                            //  a sortable value has been sent
                            case 's' :
                              //  get the attributes
                              sortableDataType = field.getAttribute('t');
                              //  get the data
                              if (field.firstChild) sortableValue = field.firstChild.data;
                              break;
                          }
                    
                          //  get the next part of the field definition
                          field = field.nextSibling;
                        }

                        //  add the cell to the current row
                        var cell = new WATTableCell(fieldValue);
                        
                        //  if filterValue is null, the value of the cell is used to filter
                        cell.filterValue = filterValue;
                        
                        //  set additional data
                        if (sortableValue)
                        {
                          //  set the sortable value
                          cell.sortableValue = sortableValue;
                          cell.sortDataType = sortableDataType;
                        }
                        else
                        {
                          //  there is no sortable value, modify the data type if it has been sent
                          cell.sortDataType = valueDataType;
                        }
                        
                        //  add the cell to the row
                        cells[fieldName] = cell;
                      }
                      break;
                  }
                
                  //  get the next field
                  row = row.nextSibling;
                }
              
                //  the row has been completely parsed, check if the row should be replaced
                if (key && replace)
                {
                  //  search the existing row
                  for (var i in tableView.rows)
                    if (tableView.rows[i].key == key)
                    {
                      var tableRow = tableView.rows[i];
                      tableRow.href = href;
                      tableRow.cells = cells;
                      tableView.__UpdateCells(tableRow);
                    }
                }
                
                //  insert the item if it can not be replaced
                if (!replace)
                {
                  //  add the data to the table view
                  var tableRow = new WATTableRow(cells);
                  tableRow.key = key;
                  tableRow.d1 = d1;
                  tableRow.d2 = d2;
                  tableRow.d3 = d3;
                  tableRow.href = href;
                  tableView.AddRow(tableRow, groups);
                }
                
                //  select the row if the auto select flag is set
                if (autoSelect && tableRow) tableView.SelectRow(tableRow);
                break;
            }
          
            //  get the next part of the table
            table = table.nextSibling;
          }
        }
        else
        {
          alert('the table with key ' + tableName + ' was not found');
        }
        break;
        
      //  an error was sent
      case 'error' :
        //  show an error message if errors should not be suppressed
        if (!suppressErrors)
        {
          //  show the error message
          var message = node.getElementsByTagName('message');
          if (message && message.item(0)) alert(message.item(0).firstChild.data);
        }
        break;
    }
    
    //  get the next node
    node = node.nextSibling;
  }
}

