/*
* module.js
* Class definition for a module.
*/

/*
* Module Constructor
*
* Creates a new Module object.
* Accepts a name and the channel id.
*/
function Module(title, cid){
   this.column = 0;
   this.title = title;
   this.cid = cid;
   this.id = guid();
   this.content = 'Cargando ...';
   this.isDragging = false;
   this.defaultExpand = false;
   this.expanded = false;
   this.canEdit = false;
   this.isEditing = false;
   this.Params = {};
}

Module.prototype.finishEdit = function(){
  var form = ge ("mod_form_" + this.id)
  var elems =  form.getElementsByTagName('INPUT');
  for(var i=0; i < elems.length; i++){
    if (elems[i].name) this.Params[elems[i].name] = elems[i].value;
  }
  this.isEditing = false;
  this.doContentUpdate();
}

Module.prototype.cancelEdit = function(){
  this.isEditing = false;
  this.doContentUpdate();
}


Module.prototype.toggleEdit = function(){
  if (this.isEditing) this.cancelEdit();
  else if (this.canEdit) {
    this.startEdit();
    this.doContentUpdate();
  }
}

Module.prototype.startEdit = function(){
  this.isEditing = true;
//  doContentUpdate();
}



Module.prototype.getID = function(){return this.id;}

Module.prototype.getTitle = function(){return this.title;}
Module.prototype.setTitle = function(title){
   this.title = title;
   var el = ge('module_title'+this.id);
   if (el) el.innerHTML = this.title;
}

Module.prototype.getContent = function(){return this.content}
Module.prototype.setContent = function(content){
   this.content = content;
   var el = ge('module_content'+this.id);
   if (el) el.innerHTML = this.content;
}

Module.prototype.setRefresh = function (seconds) {
   this.refreshInterval = seconds;
   this.lastRefresh = new Date().getTime();
}

Module.prototype.getContentUrl = function() { 
  var url = 'content.php?id='+this.id+'&cid='+this.cid;
  for (var prm in this.Params) url += '&' + prm + '=' + this.Params[prm];
  if (this.isEditing) url += "&mode=e";
  return (url); 
}

Module.prototype.doContentUpdate = function() { 
//  alert (this.getContentUrl());
  if (this.cid) makeXMLRequest(this.getContentUrl(), handleContentUpdate); 
  this.lastRefresh = new Date().getTime();
}

Module.prototype.doRefresh = function(now) {
  if (this.refreshInterval) {
    if (((now - this.lastRefresh)/1000) >= this.refreshInterval) {
//       alert ("Refreshing from " + this.getContentUrl());
       this.doContentUpdate();
    }
  }
}

Module.prototype.getXML = function() {
  var params = "";
  for (var prm in this.Params) params += '<NAME>' + prm + '</NAME><VALUE>' + this.Params[prm] + '</VALUE>';
  return ("<MOD>" +
          " <CID>" + this.cid + "</CID>" +
          " <COL>" + this.column + "</COL>" +
          " <TITLE><![CDATA[" + this.title + "]]></TITLE>" +
          " <EXPAND>" + this.expanded + "</EXPAND>" +
          " <CANEDIT>" + this.canEdit + "</CANEDIT>" +
          " <PARAMS>" + params + "</PARAMS>" +
          "</MOD>\n");
}

buildModuleFromXML = function (xmlNode) {
  var cid =  xmlNode.getElementsByTagName('CID')[0].firstChild.data;
  var col =  xmlNode.getElementsByTagName('COL')[0].firstChild.data;
  var title =  xmlNode.getElementsByTagName('TITLE')[0].firstChild.data;
  var expand =  xmlNode.getElementsByTagName('EXPAND')[0].firstChild.data;
  var canedit =  xmlNode.getElementsByTagName('CANEDIT')[0].firstChild.data;

  var mod = new Module (title, cid);
  mod.column = parseInt(col);
  mod.defaultExpand = (expand == "true");
  mod.canEdit = (canedit == "true");

  try {
    var paramsNode = xmlNode.getElementsByTagName('PARAMS')[0];
    var names = paramsNode.getElementsByTagName('NAME');
    var values = paramsNode.getElementsByTagName('VALUE');
    for(var i=0; i < names.length; i++) {
      var n  = names[i].firstChild.data;
      var v  = values[i].firstChild.data;
      mod.Params[n] = v;
    }
  }
  catch (ex) { alert ("Sorry - there was error loading the Parameters for module '" + title + "'."); } 
  return (mod); 
}

/************************** DOM-related functions *****************************/

Module.prototype.getHTML = function(){

   // Allow modules to be expanded by default
   if (this.defaultExpand){
      var contentClass = 'content display_block';
      var expandClass  = 'module_expand expand';
      this.expanded = true;
   } else {
      var contentClass = 'content';
      var expandClass = 'module_expand';
      this.expanded = false;
   }


   // Create components

   var moduleFrame = cex("DIV", {
      id:'module_frame'+this.id,
      className:'module_frame',
      onmouseover:this.fc_module_onmouseover(),
      onmouseout:this.fc_module_onmouseout()
      });

   var module = cex("DIV", {
      id:'module'+this.id,
      className:'module'
      });
      
   var header = cex("DIV", {
      id:'module_header'+this.id,
      className:'header',
      onmousedown: this.fc_header_onmousedown(),
      onmouseup: this.fc_header_onmouseup()
      });
   
   var title  = cex("H4", {
      id:'module_title'+this.id,
      className:'module_title',
      innerHTML: this.getTitle()
      });
      
   var expand  = cex("div", {
      id:'module_expand'+this.id,
      onclick:this.fc_expand_onclick(),
      className:expandClass,
      innerHTML: ''
      });
      
   var expandImage = cex("IMG", {
      id:'expand_image'+this.id,
      src:"img/deletenode.gif"})
      
   var closer = cex("div", {
      id:'module_close'+this.id,
      onclick:this.fc_close_onclick(),
      /*onmouseover:this.fc_close_onmouseover(),
      onmouseout:this.fc_close_onmouseout(),*/
      className:'module_close',
      innerHTML: 'X'
      });
  
  var edit = null;
  if (this.canEdit) edit = cex("div", {
      id:'module_edit'+this.id,
      onclick:this.fc_edit_onclick(),
      //onmouseover:this.fc_close_onmouseover(),
      //onmouseout:this.fc_close_onmouseout(),
      className:'module_edit',
      innerHTML: 'e'
      });
   
   var content = cex("div", {
      id:'module_content'+this.id,
      className:contentClass,
      innerHTML:this.content
      });
      

   // Build DIV
   ac (moduleFrame, ac (
      module,
      ac(
	 header,
         expand,
         title,
         closer,
         edit
      ),
      content));
      
   return moduleFrame;
}

Module.prototype.highlight = function(){
   // Show normally hidden elements
   ge("module"+this.id).className = 'module highlight';
   
   // Highlight the frame
   ge('module_frame'+this.id).className = 'module_frame module_frame_active';
}

Module.prototype.lowlight = function(){
   ge("module"+this.id).className = 'module';
   ge('module_frame'+this.id).className = 'module_frame';
}

Module.prototype.expand = function(){
   ge('module_content'+this.id).className = 'content display_block'
   ge('module_expand'+this.id).className = 'module_expand expand';
   this.expanded = true;
}

Module.prototype.collapse = function(){
   ge('module_content'+this.id).className = 'content';
   ge('module_expand'+this.id).className = 'module_expand collapse';
   this.expanded = false;
}

Module.prototype.close = function(){
   ge('module_frame'+this.id).style.display = 'none';
   MM.removeModule(this.id);
}

Module.prototype.startDrag = function(mouseX, mouseY){
   this.isDragging = true;
   MM.isDragging = true

   // Grab the module's frame
   var mod = ge('module_frame'+this.id);

   // Gather position & dimension information
   var pos = getXY(mod);      ;
   var x   = pos.x;
   var y   = pos.y
   var w   = mod.clientWidth;
   var h   = mod.clientHeight;
   this.dragOffsetX = mouseX - x;
   this.dragOffsetY = mouseY - y;
   
   // Create dummy outline DIV to hold place
   var dummy = cex("DIV", {id:'drag_dummy'});
   dummy.style.height = (h) + 'px';
   dummy.style.width  = (w) + 'px';
   dummy.style.top    = (y-4)   + 'px';
   dummy.style.left   = (x-4)   + 'px';
   ac(document.body, dummy);
   
   // Convert module frame to absolutely positioned element
   mod.className = 'module_frame dragging';
   mod.style.left   = x + 'px';
   mod.style.top    = y + 'px';
   mod.style.width  = w + 'px';
   mod.style.height = h + 'px';
   
   // Remove module from column
   mod.parentNode.replaceChild(dummy, mod);
   document.body.appendChild(mod);

   // Assign handler to mousemove event
   MM.dragFunction = this.fc_drag_mousemove();
   addListener(document, "mousemove", MM.dragFunction);

   
   // Suspend all mouse event handlers until drag stop
   document.body.appendChild(cex("div", {id:'info'}));
}

Module.prototype.dragTo = function(mouseX, mouseY){
   var mod = ge('module_frame'+this.id);
   mod.style.left = (mouseX - this.dragOffsetX) + 'px';
   mod.style.top  = (mouseY - this.dragOffsetY) + 'px';
   
   var c = MM.getColumnByMousePosition(mouseX, mouseY);
   if (c != -1){
      var m = MM.getModuleByColumnAndMousePosition(c, this.id, mouseX, mouseY);
      
      this.column = c;

      // If we're inserting dummy outline before a module and it's not this module
      if (m != null){
            // This dummy / newDummy crap fixes Opera
            var dummy = ge('drag_dummy');
            dummy.style.visibility='hidden';
            var newDummy = dummy.parentNode.removeChild(dummy);
            var el = ge('module_frame'+m.id);
            el.parentNode.insertBefore(newDummy, el);
            newDummy.style.visibility='visible';
      } else {

         // This dummy / newDummy crap fixes Opera
         var dummy = ge('drag_dummy')
         dummy.style.visibility='hidden';
         var newDummy = dummy.parentNode.removeChild(dummy);
         ge('column'+c).appendChild(newDummy);
         newDummy.style.visibility='visible';
         
         
         
      }
      
   }
}

Module.prototype.stopDrag = function(){
   var dummy = ge('drag_dummy');
   var el    = ge('module_frame'+this.id);
   el.className = 'module_frame';

   dummy.parentNode.replaceChild(el, dummy);

   removeListener(document, "mousemove", MM.dragFunction);

   this.isDragging = false;
   MM.isDragging = false;
   
   el.style.left   = '';
   el.style.top    = '';
   el.style.width  = '';
   el.style.height = '';
   
   // Fire mouseout in case user dropped off target
   this.fc_module_onmouseout()();
}




/********************** Event Handlers ****************************************/
Module.prototype.fc_expand_onclick = function(){
   var _this = this;
   return function(evt){
      if (_this.expanded)
         _this.collapse();
      else
         _this.expand();
         

      if (!evt) var evt = window.event;
      // if (evt.cancelBubble) evt.cancelBubble();
      // if (evt.stopPropagation) evt.stopPropagation();

      var t = (evt.target) ? evt.target : evt.srcElement;

   }
}

Module.prototype.fc_header_onmousedown = function(){
   var _this = this;
   return function(evt){
      if (!evt) var evt = window.event;
      
      var t = (evt.target) ? evt.target : evt.srcElement;
      if (t.className == 'header' || t.className == 'module_title')
         if (!_this.isDragging)
            _this.startDrag(evt.clientX, evt.clientY);

   }
}

Module.prototype.fc_header_onmouseup = function(){
   var _this = this;
   return function(){
      if (_this.isDragging)
         _this.stopDrag();
   }
}

Module.prototype.fc_drag_mousemove = function(){
   var _this = this;
   return function(evt){
      if (!evt) var evt = window.evt;
      _this.dragTo(evt.clientX, evt.clientY);
   }
}

Module.prototype.fc_close_onclick = function(){
   var _this = this;
   return function(){
      _this.close();
   }
}

Module.prototype.fc_edit_onclick = function(){
   var _this = this;
   return function(){
      _this.toggleEdit();
   }
}

Module.prototype.fc_close_onmouseover = function(){
   var _this = this;
   return function(){
      ge('module_close'+_this.id).className = 'module_close module_close_hover';
   }
}

Module.prototype.fc_close_onmouseout = function(){
   var _this = this;
   return function(){
      ge('module_close'+_this.id).className = 'module_close';
   }
}

Module.prototype.fc_module_onmouseover = function(){
   var _this = this;
   return function(){
      if (!_this.isDragging)
         _this.highlight();
   }
}

Module.prototype.fc_module_onmouseout = function(){
   var _this = this;
   return function(){
      if (!_this.isDragging)
         _this.lowlight();
   }
}

