// *********************************************************************
// *                   GLOBALS					       *
// *********************************************************************

var supervisor = null;

// *********************************************************************
// *                   ENUMERATIONS				       *
// *********************************************************************

var EBrowser =
{
   Konqueror: 1,
   Opera: 2,
   Netscape: 3,
   IExplorer: 4,
   Firefox: 5,
   Safari: 6,
   Unknown: 7,
   Chrome: 8
}

// *********************************************************************
// *                   EVENTS					       *
// *********************************************************************

// * Supervisor_OnMouseMove(SENDER, e)
// * Supervisor_OnMouseDown(SENDER, e)
// * Supervisor_OnMouseUp(SENDER, e)
// * Supervisor_OnResize(SENDER)

// *********************************************************************
// *                   DOCUMENT SUPERVISOR			       *
// *********************************************************************

function Supervisor()
{
   var MySelf = this;
   
   this.MouseMove = function(e)
   {
      if (!e) var e = window.event;
      
      if (e.pageX || e.pageY)
      {
         MySelf.mouse.x = e.pageX;
         MySelf.mouse.y = e.pageY;
      }
      else if (e.clientX || e.clientY)
      {
         MySelf.mouse.x = e.clientX + document.documentElement.scrollLeft;
         MySelf.mouse.y = e.clientY + document.documentElement.scrollTop;
      }
      MySelf.LoadEvent('Supervisor_OnMouseMove', e);
      MySelf.CheckOverDropsTargets();
   }
   
   this.ScrollMove = function(e)
   {
      if (!e) var e = window.event;
      if (e.pageX || e.pageY)
      {
         MySelf.mouse.x = e.pageX;
         MySelf.mouse.y = e.pageY;
      }
      else if (e.clientX || e.clientY)
      {
         MySelf.mouse.x = e.clientX + document.documentElement.scrollLeft;
         MySelf.mouse.y = e.clientY + document.documentElement.scrollTop;
      }
      MySelf.LoadEvent('Supervisor_ScrollMove', e);
      MySelf.CheckOverDropsTargets();
   }
   
   this.MouseDown = function(e)
   {
      MySelf.UpdateButtonsStatus(e);
      MySelf.LoadEvent('Supervisor_OnMouseDown', e);
   }
   
   this.MouseUp = function(e)
   {
      MySelf.UpdateButtonsStatus(e);
      MySelf.CheckUpDropsTargets();
      MySelf.LoadEvent('Supervisor_OnMouseUp', e);
   }
   
   this.OnResize = function()
   {
      if(MySelf.wHeight != document.body.offsetHeight || MySelf.wWidth != document.body.offsetWidth)
      {
         MySelf.wHeight = document.body.offsetHeight;
   	 MySelf.wWidth = document.body.offsetWidth;
      	 MySelf.LoadEvent('Supervisor_OnResize', null);
      }
   }

   this.New();
}

Supervisor.prototype =
{
   mouse: null,
   wHeight: 0,
   wWidth: 0,
   customs: null,
   browser: null
}

// *********************************************************************
// *                   PRIVATE					       *
// *********************************************************************

Supervisor.prototype.New = function()
{
   this.DetectBrowser();
   this.mouse = new Point(0, 0);
   this.mouse.rightButtonPushed = false;
   this.mouse.rightButtonPushed = false;
   this.wHeight = document.body.offsetHeight;
   this.wWidth = document.body.offsetWidth;
   this.customs = {};
   this.customs['Supervisor_dropTargets'] = {};
   this.customs['Supervisor_GarbagesCollector'] = {};
   
   AttachEvent(document, 'mousemove', this.MouseMove);
   AttachEvent(document, 'mousedown', this.MouseDown);
   AttachEvent(document, 'mouseup', this.MouseUp);
   AttachEvent(window, 'scroll', this.ScrollMove);
   AttachEvent(window, 'resize', this.OnResize);
   AttachEvent(window, 'unload', function() { supervisor.LoadEvent('Supervisor_OnCleanGarbage'); });
}

Supervisor.prototype.CheckUpDropsTargets = function()
{
   if(this.customs['Supervisor_attachedObject'] != null)
   {
      var fireredObjet = null;
      for(var key in this.customs['Supervisor_dropTargets'])
      {
         if(key != 'xml') // * Firefox fix
         {
            var obj = this.customs['Supervisor_dropTargets'][key];
            if(obj != null && obj.id != this.customs['Supervisor_attachedObject'].id)
            {
               var endX = obj.position.x + obj.handle.offsetWidth;
               var endY = obj.position.y + obj.handle.offsetHeight;
               if(this.mouse.x >= obj.position.x && this.mouse.x <= endX 
                  && this.mouse.y >= obj.position.y && this.mouse.y <= endY)
               {
                  if(fireredObjet == null 
                     || (obj.css.zIndex > fireredObjet.css.zIndex)) { fireredObjet = obj; }
               }
            }
         }
      }
      if(fireredObjet != null) { fireredObjet.HandleOnDrop(); }
   }
}

Supervisor.prototype.CheckOverDropsTargets = function()
{
   for(var key in this.customs['Supervisor_dropTargets'])
   {
      if(key != 'xml') // * Firefox fix
      {
         var obj = this.customs['Supervisor_dropTargets'][key];
         if(obj != null)
         {
            // ** offsetLeft(obj.handle) and offsetTop(obj.handle) will be better but use too much cpu
            // ** need to refresh obj childs position.x and position.y after mouse up
            var endX = obj.position.x + obj.handle.offsetWidth;
            var endY = obj.position.y + obj.handle.offsetHeight;
            if(this.mouse.x >= obj.position.x && this.mouse.x <= endX 
               && this.mouse.y >= obj.position.y && this.mouse.y <= endY)
            {
               if(!obj.over){ obj.HandleMouseOver(); }
               obj.over = true;
            }
            else
            {
               if(obj.over) { obj.HandleMouseOut(); }
               obj.over = false;
            }
         }
      }
   }
}

Supervisor.prototype.UpdateButtonsStatus = function(e)
{
   switch(e.button)
   {
      case 0:    
      case 1:    this.mouse.rightButtonPushed = true;
   		 this.mouse.leftButtonPushed = false;
   		 break;
   		   
      case 2:    this.mouse.rightButtonPushed = false;
	   	 this.mouse.leftButtonPushed = true;
   		 break;
   		 
      default:   this.mouse.rightButtonPushed = false;
	   	 this.mouse.leftButtonPushed = false;
   		 break;
   } 
}

Supervisor.prototype.DetectBrowser = function()
{
   var agent = navigator.userAgent.toLowerCase();
   if(agent.indexOf('konqueror') != -1) { this.browser = EBrowser.Konqueror; }
   else if(agent.indexOf('opera') != -1) { this.browser = EBrowser.Opera; }
   else if(agent.indexOf('netscape') != -1) { this.browser = EBrowser.Netscape; }
   else if(agent.indexOf('msie') != -1) { this.browser = EBrowser.IExplorer; }
   else if(agent.indexOf('firefox') != -1) { this.browser = EBrowser.Firefox; }
   else if(agent.indexOf('safari') != -1 && agent.indexOf('chrome') == -1) { this.browser = EBrowser.Safari; }
   else if(agent.indexOf('chrome') != -1) { this.browser = EBrowser.Chrome; }
   else { this.browser = EBrowser.Unknown; }
}

// *********************************************************************
// *                   EVENTS					       *
// *********************************************************************

Supervisor.prototype.LoadEvent = function(name, object)
{
  try
   {
      eval(name + '(this' + ((object == null) ? ')' : ', object)'));
   }
   catch(e) { }
}

// *********************************************************************
// *                   INTERNAL EVENTS				       *
// *********************************************************************

function Supervisor_OnCleanGarbage(sender)
{
   for(key in sender.customs['Supervisor_GarbagesCollector'])
   { if(key != 'xml') { sender.customs['Supervisor_GarbagesCollector'][key] = null; } }
}

// *********************************************************************
// *            MEMORY LEAK PATCH				       *
// *********************************************************************

Supervisor.prototype.FireEvent = function(id, event, e)
{
   this.customs['Supervisor_GarbagesCollector'][id].LoadEvent(event, e);
}

Supervisor.prototype.RegisterGarbage = function(garbage, id)
{
   this.customs['Supervisor_GarbagesCollector'][id] = garbage;
}
