//ObjectManager.js
//this object attempts to connect messages spawned by GUIWidgets to their appropriate functions.
//basically it maintains a list of element names, with a series of pointers to their associated objects.
//The prototype GUIWidget object needs to register its elements when they are created.
//There should only be one of these per application.  With this in mind, it will always be named OBJECT_MANAGER.

//New for version 3:  
//      extension manager.  Will have all widget and control types registered
//      also will handle bindings between xml parser functions and the corresponding objects

//<objectName>.js
//
//------------------------------------------
//Dependancies:
//  

ObjectManager = function( )
{
  this.messageBindings = new Array();  //links an object id to the object itself
  this.objectList = new Array();       //struct with attribute names of an object name; value of attribute is pointer to object
  this.objectIndex = new Array();      //Lookup table for objects

  this.valueList = new Array();
  this.valueIndex = new Array();

  this.controlList = new Array();
  this.controlIndex = new Array();

  this.extensions = new Object();
  /**********************************************
   new code to support object type registration
  **********************************************/
  this.widgetRegistry = new Object();
  this.controlRegistry = new Object();
};

OBJECT_MANAGER = new ObjectManager();   //global variable


/*************************************************

  Registration functions for individual objects, 
  widget types, control types.

*************************************************/


ObjectManager.prototype.registerObject = function(objectName, objectPointer)
{
  //alert("In registerObject, the object name is "+objectName + " and the new messageBinding index is "+messageBindings.length);
  var objectID = this.messageBindings.length;
  this.messageBindings[this.messageBindings.length] = new Array(objectName, objectPointer);
  this.objectList[objectName] = objectPointer;
  this.objectIndex[this.objectIndex.length] = objectName;
  return objectID;
};

ObjectManager.prototype.registerWidget = function (widgetType, prototype)
{
  this.widgetsRegistry[widgetType] = prototype;
};

ObjectManager.prototype.registerExtension = function (extensionId, setActiveState)
{
  this.extensions[extensionId] = setActiveState;
};


/**************************************************

  Event handling functions

*************************************************/


ObjectManager.prototype.processEvent = function(e)
{
  var evt = new xEvent(e);
  //dprintf('In object manager, processing an event of type '+evt.type+' for entity number '+parseInt(evt.target.objectManagerId));
  if (!isNaN(parseInt(evt.target.objectManagerId)))
  {
    switch (evt.type)
    {
      case 'click':
	      this.messageBindings[parseInt(evt.target.objectManagerId)][1].clickCallback(evt);
	      break;
      case 'mousedown':
        this.messageBindings[parseInt(evt.target.objectManagerId)][1].mouseDownCallback(evt);
        break;
      case 'mouseup':
        this.messageBindings[parseInt(evt.target.objectManagerId)][1].mouseUpCallback(evt);
        break;
      case 'mousemove':
        this.messageBindings[parseInt(evt.target.objectManagerId)][1].mouseMoveCallback(evt);
        break;
      case 'mouseover':
        this.messageBindings[parseInt(evt.target.objectManagerId)][1].mouseOverCallback(evt);
        break;
      case 'mouseout':
        this.messageBindings[parseInt(evt.target.objectManagerId)][1].mouseOutCallback(evt);
        break;
      case 'keypress':
        this.messageBindings[parseInt(evt.target.objectManagerId)][1].keyPressCallback(evt);
        break;
      case 'keyup':
        this.messageBindings[parseInt(evt.target.objectManagerId)][1].keyUpCallback(evt);
        break;
      case 'keydown':
        this.messageBindings[parseInt(evt.target.objectManagerId)][1].keyDownCallback(evt);
        break;
      case 'drag':
        this.messageBindings[parseInt(evt.target.objectManagerId)][1].dragCallback(evt);
        break;
      case 'dragStart':
        this.messageBindings[parseInt(evt.target.objectManagerId)][1].dragStartCallback(evt);
        break;
      case 'dragEnd':
        this.messageBindings[parseInt(evt.target.objectManagerId)][1].dragEndCallback(evt);
        break;
      case 'change':
        this.messageBindings[parseInt(evt.target.objectManagerId)][1].changeCallback(evt);
        break;
      case 'focus':
        this.messageBindings[parseInt(evt.target.objectManagerId)][1].focusCallback(evt);
        break;
      default:
        //alert(evt.type);
        break;
    }
  }
};

ObjectManager.prototype.setGuiValue = function(valueName, newValue)
{
  this.valueList[valueName] = newValue;
  this.valueIndex[this.valueIndex.length] = valueName;
  return this.valueList[valueName];
};

ObjectManager.prototype.getGuiValue = function(valueName)
{
  switch (valueName)
  {
    case '_PAGEWIDTH_':
      return xClientWidth();
      break;
    case '_PAGEHEIGHT_':
      return xClientHeight();
      break;
    default:
      return this.valueList[valueName];
      break;
  }
};


ObjectManager.prototype.addControl = function(controlPointer,controlType, controlId)
{
  /**
    TODO:  REWRITE!
    INSTEAD OF A SWITCH STATEMENT, CHECK THE CONTROL REGISTRY
    Only registered controls can be used, otherwise a warning will be given.
    This helps to force all controls to follow the proper structure...
  **/
  switch (controlType)
  {
    case 'layerControl':
    case 'radioButtonGroup':
    case 'map':
    case 'labelControl':
    case 'queryControl':
    case 'selectionControl':
      this.controlList[controlId] = new Array(controlPointer, controlType);
      this.controlIndex[this.controlIndex.length] = new Array(controlId, controlType);
      break;
    default:
      alert('Object Manager Error:\nUnknown control type "'+controlType+'"\nControl id = "'+controlId+'"');
      break;
  }
};

ObjectManager.prototype.getControl = function(controlId)
{
  if (this.controlList[controlId])
    return this.controlList[controlId][0];
  else
    return null;
};


ObjectManager.prototype.extensionIsRegistered = function (extensionId)
{
  if (this.extensions[extensionId])
    return true;
  else
    return false;
};

ObjectManager.prototype.getWidgetAttribute = function(widgetName, attributeName)
{
  var widget = this.objectList[widgetName];
  switch (attributeName)
  {
    case 'width':
      return widget.width();
      break;
    case 'height':
      return widget.height();
      break;
    case 'left':
    case 'xpos':
      return widget.left();
      break;
    case 'top':
    case 'ypos':
      return widget.top();
      break;
    case 'right':
      return widget.left()+widget.width();
      break;
    case 'bottom':
      return widget.top()+widget.height();
      break;
    case 'zpos':
      return widget.zIndex;
      break;
    default:
      return null;
  }
};

function EVENT_LISTENER(e)
{
  //global convienance function to communicate with object manager
  //also a nice place for monitoring events during a debug session
  //catches event message and moves it along to the object manager
  //This function is called for every event that is attached to a widget
  /*evt = e;
    dprintf('Event Details:<br>Target Element:  '+evt.target+'<br>'+
          'GUILib target:  '+parseInt(evt.target.objectManagerId)+':  '+this.objectIndex[parseInt(evt.target.objectManagerId)]+'<br>'+
          'event type:  '+evt.type+'<br>'+
          'page coordinates:  ('+evt.pageX+','+evt.pageY+')<br>'+
          'relative coordinates:  ('+evt.offsetX+','+evt.offsetY+')<br>'+
          'corrected coordinates for image buttons:  ('+(evt.offsetX+xLeft(evt.target))+','+evt.offsetY+')<br>'+
          'key code:  '+evt.keyCode
         );
    */      
  
  OBJECT_MANAGER.processEvent(e);
};

/**************************************************

      Debug / documentation functions

**************************************************/

ObjectManager.prototype.listGuiValues = function()
{
  listString = '<table border = "1"><tr><td colspan = "3" align="center">GUI values:</td></tr>';
  listString = listString+'<tr><td>Index</td><td>Name</td><td>Value</td></tr>';
  for (i=0; i<this.valueIndex.length; i++)
  {
    listString = listString+'<tr><td>'+i+'</td><td>'+this.valueIndex[i]+'</td><td>'+this.valueList[this.valueIndex[i]]+'</td></tr>';
  }
  listString = listString + '</table>';
  return (listString);
};

ObjectManager.prototype.listGuiWidgets = function()
{
  listString = '<table border = "1"><tr><td colspan="2" align="center">GUI Widgets:</td></tr>';
  listString = listString+'<tr><td>Index</td><td>Name</td></tr>';
  for (i=0; i<this.objectIndex.length; i++)
  {
    listString = listString+'<tr><td>'+i+'</td><td>'+this.objectIndex[i]+'</td></tr>';
  }
  listString = listString + '</table>';
  return (listString);
};

ObjectManager.prototype.listGuiControls = function()
{
  listString = '<table border = "1"><tr><td colspan = "3" align="center">GUI Controls:</td></tr>';
  listString = listString+'<tr><td>Index</td><td>Name</td><td>Type</td></tr>';
  for (i=0; i<this.controlIndex.length; i++)
  {
    listString = listString+'<tr><td>'+i+'</td><td>'+this.controlIndex[i][0]+'</td><td>'+this.controlIndex[i][1]+'</td></tr>';
  } 
  listString = listString + '</table>';
  return (listString);
};

/**************************************************

  Add utility functions to the document object

**************************************************/

document.getWidgetById = function (objectName)
{
  return (OBJECT_MANAGER.objectList[objectName]);
};

document.getGuiValue = function (valueName)
{
  return OBJECT_MANAGER.getGuiValue(valueName);
};

document.getGuiControl = function (valueName)
{
  return OBJECT_MANAGER.getControl(valueName);
};


/*************************************************
      Deprecated Methods
*************************************************/

document.getGuiWidgetById = function (objectName)
{
  alert('Warning:  getGuiWidgetById has been deprecated.\nUse getWidgetById instead');  
  return document.getWidgetById(objectName);
};

document.getGuiValueById = function (valueName)
{
  alert('Warning:  document.getGuiValueById has been deprecated.\nUse getGuiValue instead');
  return document.getGuiValue(valueName);
};


