/**
 * ToolCollection class.
 * Each collection has a single "selected" tool
 *
 * Properties:
 *    dom
 *    tools - array of ToolInfo objects 
 *    selectedTool - reference to the ToolInfo instance for the currently selected tool
 * 
 * Methods:
 *    toString
 *   
 * TODO: handle mutually exclusive tools: identify/identifyall; hyperlink/hyperlinkAny
 */
function ToolCollection(dom) {
   log.trace('inside constructor for ToolCollection...');
   this.dom = dom;
   this.tools = new Array();
   this.selectedTool = null;   
   var children = dom.getElementsByTagName("tools")[0].childNodes;
   
   var type;
   var tool;
   for (var i=0; i<children.length; i++) {
      if (children[i].nodeName == "tool") {
         type = "tool";
      } else if (children[i].nodeName == "command") {
         type = "command";
      } else {
         continue;
      }
      
      /*
      //only load active tools
      if (children[i].getAttributeNode("active") && children[i].getAttributeNode("active").nodeValue !== "true") {
         continue;
      }
      */
      
      tool = new ToolInfo(children[i],type);
      if (children[i].getAttributeNode("selected") && children[i].getAttributeNode("selected").nodeValue == "true") {
         this.selectedTool = tool;
      }
      //log.debug('adding tool '+tool.name+'...');
      this.tools.push(tool);
   }
}


//WARNING: XMLSerializer will not pickup changes to object after node passed in
ToolCollection.prototype.toString=function() {
   return((new XMLSerializer()).serializeToString(this.dom));
}


/**
 * add a ToolInfo interactively. primarily used for debugging
 */
ToolCollection.prototype.addTool=function(icon_active,icon_inactive,name,description,id,callback) {
   var tool = new ToolInfo();
   tool.type = 'tool';
   tool.active = true;
   tool.icon_active = icon_active;
   tool.icon_inactive = icon_inactive;
   tool.name = name;
   tool.description = description;
   tool.id = id;
   tool.callback = callback;
   log.debug('adding tool '+tool.name);
   this.tools.push(tool);
}
 
 
ToolCollection.prototype.addCommand=function(icon_inactive,name,description,id,callback) {
   var tool = new ToolInfo();
   tool.type = 'command';
   tool.active = true;
   tool.icon_inactive = icon_inactive;
   tool.name = name;
   tool.description = description;
   tool.id = id;
   tool.callback = callback;
   this.tools.push(tool);
}


/**
 * return a ToolInfo object for the tool w/ specified id (toolMode). returns 
 * null if none found w/ specified id
 */
ToolCollection.prototype.getToolById=function(id) {
   for (var i=0; i<this.tools.length; i++) {
      if (this.tools[i].id == id) {
         return(this.tools[i]);
      }
   }
   return(null);
}


/**
 * return a ToolInfo object for the tool w/ specified name. returns null if none
 * found w/ given name
 */
ToolCollection.prototype.getToolByName=function(name) {
   for (var i=0; i<this.tools.length; i++) {
      if (this.tools[i].name == name) {
         return(this.tools[i]);
      }
   }
   return(null);
}


/**
 * supplement/override the default configuration w/ a local configuration
 * 
 * given a DOM representing the configuration files
 */
ToolCollection.prototype.loadCustom=function(dom) {
   log.trace('inside loadCustom...');
   var children = dom.getElementsByTagName("tools")[0].childNodes;
   var type;
   var tool;
   var toolName;
   var theNode;
   for (var i=0; i<children.length; i++) {
      theNode = children[i];
      if (theNode.nodeName == "tool") {
         type = "tool";
      } else if (theNode.nodeName == "command") {
         type = "command";
      } else {
         continue;
      }
      
      toolName = theNode.getAttributeNode("name").nodeValue;
      tool = this.getToolByName(toolName); 
      if (tool == null) {
         //new tool - construct ToolInfo and add to array
         log.debug('adding new tool '+toolName+'...');
         tool = new ToolInfo(theNode,type);
         this.tools.push(tool);
         
      } else {
         //update existing tool
         log.debug('updating existing tool '+toolName);
         
         //override default tool's active status
         if (theNode.getAttributeNode("active")) {
            var v = theNode.getAttributeNode("active").nodeValue;
            if  (v == "true") {
               tool.active = true;
            } else if (v == "false") {
               tool.active = false;
            } else {
               log.warn('Unexpected value for active attribute in tools.xml: '+v);
            }
         }
         
         /* no current use case for overriding icon or behavior of default tool
         if (theNode.getAttributeNode("icon_active")) {
            tool.icon_active = theNode.getAttributeNode("icon_active").nodeValue;
         }
         if (theNode.getAttributeNode("icon_inactive")) {
            tool.icon_inactive = theNode.getAttributeNode("icon_inactive").nodeValue;
         }
         if (theNode.getAttributeNode("function")) {
            tool.callback = theNode.getAttributeNode("function").nodeValue;
         }
         */
                  
      }
            
      //if more than one marked as selected, last in list wins. 
      if (children[i].getAttributeNode("selected") && 
          children[i].getAttributeNode("selected").nodeValue == "true" &&
          tool.active == true) {
         this.selectedTool = tool;
      }
   }
   
   //now that ToolCollection has been modified, remove inactive tools
   this.pruneList();
   
}


/**
 * remove all inactive tools from list
 */
ToolCollection.prototype.pruneList=function() {
   log.trace('inside prunelist...');
   this.tools = this.tools.reject(function(n) {
      return(n.active == false);
   });
}


/*****************************************************************************/
/*****************************************************************************/
/**
 * ToolInfo class
 *
 * Properties:
 *    node DOM Element
 *    icon_active
 *    icon_inactive
 *    description
 *    toolMode
 *    callback - function called on mousedown
 *    name 
 *    type - tool or command
 *    
 * Methods:
 *    toString
 *    
 */
function ToolInfo(node,type) {
   this.node = node;
   this.icon_active;
   this.icon_inactive;
   this.description;
   this.toolMode;
   this.callback;
   this.name;
   this.type = type;  //tool or command
   this.active = false;
   
   //log.trace('inside constructor for ToolInfo...');
   if (node == null) return;
   
   //only tools have active icons and toolModes
   if ("tool" == this.type) this.icon_active = node.getAttributeNode("icon_active").nodeValue;
   if ("tool" == this.type) this.toolMode = parseInt(node.getAttributeNode("id").nodeValue);

   this.icon_inactive = node.getAttributeNode("icon_inactive").nodeValue;
   this.description = node.getAttributeNode("description").nodeValue;
   this.name = node.getAttributeNode("name").nodeValue;

   if (node.getAttributeNode("active") && node.getAttributeNode("active").nodeValue == "true") {
      this.active = true;
   }
   //assume that all callback functions loaded into MapFrame
   this.callback = "parent.MapFrame."+node.getAttributeNode("function").nodeValue+"; setToolPic('"+this.name+"')";
   //log.debug(this.callback);   
}


//WARNING: XMLSerializer will not pickup changes to object after node passed in
ToolInfo.prototype.toString=function() {
   return((new XMLSerializer()).serializeToString(this.node));
}


