// VSEventProc.js event observer pattern implemenation
// ------------------------------------------------------------
// namespace Viasoft
// Written by Viasoft Ltd. (viasoft.com.ua)
// Free permission to use granted under BSD licence

// This function will add all nessery items to targetDispatcher object
// Will add all nesery data and fucntions
// Recommended way of use (in constructor):
// initEventDispatcher(this);
var initEventDispatcher = function(targetDispatcher)
 {
  // Internal:
  // eventProcFuncArray[EventName][i] = func/object
  targetDispatcher.eventProcFuncArray = new Array();

  // Use this to init event object before dispatchEvent
  // Will add all nesery data and fucntions to event
  // Recommended way of use (in constructor):
  // myDispatcher.initEventObject(this,eventName);
  targetDispatcher.initEventObject = function(e,eventName)
   {
    if (eventName == null) { eventName = null; } // Default value

    e.eventName = eventName;
    e.getEventName = function() { return this.eventName; }

    e.eventSource = this; // Link to event dispatcher itself
    e.getEventSource = function() { return this.eventSource; }
   }

  // Base class for event proccessor
  // Must implement handleEvent method
  // Recommended way of use (in constructor):
  // myDispatcher.initEventHandlerObject(this);
  targetDispatcher.initEventHandlerObject = function(handler)
   {
    handler.handleEvent = function(e) { }
   }

  // Call this to disptach event e
  // Param e is an event to dispatch
  targetDispatcher.dispatchEvent = function(e)
   {
    function isFunction(obj)
     {
      return(typeof(obj) == "function");
     }

    function isObjectHandler(obj)
     {
      if (obj.handleEvent == null)
       {
        return(false);
       }
      else
       {
        return(typeof(obj.handleEvent) == "function");
       }
     }

    var eventName = e.getEventName();

    if (this.eventProcFuncArray[eventName] == null)
     {
     }
    else
     {
      var procFuncArray = this.eventProcFuncArray[eventName];

      for (var i = 0; i < procFuncArray.length; i++)
       {
        if (isFunction(procFuncArray[i]))
         {
          procFuncArray[i](e);
         }
        else if (isObjectHandler(procFuncArray[i]))
         {
          procFuncArray[i].handleEvent(e);
         }
        else
         {
          // Ignore
         }
       }
     }
   }

  // Add event handler/listener to eventName as procFunc/Object
  targetDispatcher.addEventHandler = function(eventName,procFuncOrObject)
   {
    if (this.eventProcFuncArray[eventName] == null)
     {
      this.eventProcFuncArray[eventName] = new Array();
      this.eventProcFuncArray[eventName].push(procFuncOrObject);
     }
    else
     {
      var procFuncArray = this.eventProcFuncArray[eventName];

      for (var i = 0; i < procFuncArray.length; i++)
       {
        if (procFuncArray[i] == procFuncOrObject)
         {
          return; // already here
         }
       }

      procFuncArray.push(procFuncOrObject);
     }
   }

  // Remove event handler/listener to eventName as procFunc/Object
  targetDispatcher.removeEventHandler = function(eventName,procFuncOrObject)
   {
    if (this.eventProcFuncArray[eventName] == null)
     {
     }
    else
     {
      var procFuncArray = this.eventProcFuncArray[eventName];

      for (var i = 0; i < procFuncArray.length; i++)
       {
        if (procFuncArray[i] == procFuncOrObject)
         {
          procFuncArray.splice(i,1);

          // Done - force end of cycle

          i = procFuncArray.length;
         }
       }

      if (procFuncArray.length <= 0)
       {
        this.eventProcFuncArray[eventName] = null;
       }
     }
   }
 };

