/*

*/
function Guider(){

  var xmldoc;
  var icon         = null;
  var logo         = null;
  var banner       = null;
  var headerType   = null;
  var introText    = null;
  var companyURL   = null;
  var contactEmail = null;
  var contactName  = null;
  var cssFile      = null;
  var contactText  = null;
  var linkLaunch   = null;
  var hasPictures  = false;
  var guiderFormat = 't'; //assume text
  var analyticsTaging = false;
  var campaignSource =  null;
  var campaignMedium =  null;
  var campaignTerm =    null;
  var campaignContent = null;
  var campaignName =    null;
  //This is the array of nodes by node id
  var nodearray = new Object();

  this.setXML = function(xmlstr){
    xmldoc = new XMLDoc();
    xmldoc.setXML(xmlstr);
    //build map of nodes by id
    var root  = xmldoc.getRoot();
    var noderoot = root.getChildByName("nodes");
    var nodes = noderoot.getChildrenByName("node");
    for (var i=0; i<nodes.length; i++){
        var node = nodes[i];
        var id = node.getAttribute("id");
        nodearray[id]=node;
    }
    //get the guider header stuff if available
    var options = root.getChildByName('portable-options');
    if (options != null){
       var icon_node         = options.getChildByName('icon');
       var logo_node         = options.getChildByName('logo');
       var banner_node       = options.getChildByName('banner');
       var headerType_node   = options.getChildByName('header-type');
       var introText_node    = options.getChildByName('intro-text');
       var companyURL_node   = options.getChildByName('company-url');
       var contactEmail_node = options.getChildByName('contact-email');
       var contactName_node  = options.getChildByName('contact-name');
       var contactText_node  = options.getChildByName('contact-text');
       var cssFile_node      = options.getChildByName('css-file');
       var guiderFormat_node = options.getChildByName('guider-type');
       var linkLaunch_node   = options.getChildByName('links-new-window');
       var analyticsTagging_node    = options.getChildByName('analytics-tagging');       
       var campaignSource_node      = options.getChildByName('campaign-source');       
       var campaignMedium_node      = options.getChildByName('campaign-medium');       
       var campaignTerm_node        = options.getChildByName('campaign-term');       
       var campaignName_node        = options.getChildByName('campaign-name');       
       var campaignContent_node     = options.getChildByName('campaign-content');       
              
       if (icon_node!=null)         icon         = icon_node.getChildByName('url').getText();
       if (logo_node!=null)         logo         = logo_node.getChildByName('url').getText();
       if (banner_node!=null)       banner       = banner_node.getChildByName('url').getText();
       if (headerType_node!=null)   headerType   = headerType_node.getText();
       if (introText_node!=null)    introText    = introText_node.getText();
       if (companyURL_node!=null)   companyURL   = companyURL_node.getText();
       if (contactEmail_node!=null) contactEmail = contactEmail_node.getText();
       if (contactName_node!=null)  contactName  = contactName_node.getText();
       if (contactText_node!=null)  contactText  = contactText_node.getText();
       if (cssFile_node!=null)      cssFile      = cssFile_node.getText();
       if (guiderFormat_node!=null) guiderFormat = guiderFormat_node.getText();
       if (linkLaunch_node!=null)   linkLaunch   = linkLaunch_node.getText();
       if (analyticsTagging_node!=null)     analyticsTagging    = analyticsTagging_node.getText();
       if (campaignSource_node!=null)       campaignSource      = campaignSource_node.getText();
       if (campaignMedium_node!=null)       campaignMedium      = campaignMedium_node.getText();
       if (campaignTerm_node!=null)         campaignTerm        = campaignTerm_node.getText();
       if (campaignContent_node!=null)      campaignContent     = campaignContent_node.getText();
       if (campaignName_node!=null)         campaignName        = campaignName_node.getText();
       hasPictures = (guiderFormat=='g'||guiderFormat=='h'||guiderFormat=='w');      
    }
  }
  this.getIcon = function(){
    return icon;
  }
  this.getLogo = function(){
    return logo;
  }
  this.getBanner = function(){   
    return banner;
  }
  this.headerTypeIsBanner = function(){
    if (headerType==null) {return false;}
    return (headerType=="banner");
  }
  this.getIntroText = function(){
    return introText;
  }
  this.getCssFile = function(){
    return cssFile;
  }
  this.hasCompanyURL = function(){
    return (companyURL!=null);
  }
  this.getCompanyURL = function(){
    return companyURL;
  }
  this.getContactEmail = function(){
    return contactEmail;
  }
  this.getContactText = function(){
    if(contactText != null){
        return contactText;
    }else{
        return "";
    }
  }
  this.hasContactName = function(){
    return (contactName!=null);
  }
  this.getContactName = function(){
    return contactName;
  }
  this.hasPictures = function(){
    return hasPictures;
  }
  this.getFormat = function(){
    return guiderFormat;
  }
  this.linksNewWindow = function(){
    return (linkLaunch!=null && linkLaunch=="1");
  }
  this.getTagParams = function(){
    if(typeof analyticsTagging != 'undefined' && analyticsTagging != null){
        return  "?utm_source="      + campaignSource +
            "&utm_medium="      + campaignMedium +
            "&utm_term="        + campaignTerm +
            "&utm_content="     + campaignContent +
            "&utm_campaign="    + campaignName;
    }else{
        return "";
    }
  }
  this.getTitle = function(){
    var rootNodeElement = xmldoc.getRoot().getChildByName("name");
    return rootNodeElement.getText();
  }
  this.getRootQuestion = function(){
    var rootNodeElement = xmldoc.getRoot().getChildByName("root-node");
    var rootid = rootNodeElement.getText();
    var node = nodearray[rootid];
    var rootQ = new Question(node);
    rootQ.setGuider(this);
    return rootQ;
  }
  this.getNode = function(id){
    var node = nodearray[id];
    var desttype = node.getAttribute('type');
    var dest = null;
    switch (desttype){
      case "Question":
           dest = new Question(node);
           break;
      case "GoogleSearch":
           dest = new Results(node);
           break;
      case "BingSearch":
           dest = new Results(node);
           break;
      case "ExternalLink":
           dest = new Results(node);
           break;
      case "SolutionPage":
           dest = new Results(node);
           break;
      case "VideoPage":
           dest = new Results(node);
           break;
      default:
           alert("Unknown destination type of '"+desttype+"' in Answer.getDestination");
           break;
    }
    dest.setGuider(this);
    return dest;
  }
  //----------------------------------------------------------------------------
  // This method gets an external link node with the given destination URL
  //----------------------------------------------------------------------------
  this.getNodeByDestination = function(desturl){
    for (var i in nodearray){
        var node = nodearray[i];
        if (node.getAttribute('type')=="ExternalLink"){
           var result = new Results(node);
           result.setGuider(this);
           if (result.getURL()==desturl){
              return node;
           }
        }
    }
    return null;
  }
  //----------------------------------------------------------------------------
  // This method gets the parent of a given node
  //----------------------------------------------------------------------------
  this.getParent = function(childnode){
    var target = childnode.getAttribute('id');
    for (var i in nodearray){
        var node = nodearray[i];
        if (node.getAttribute('type')=="Question"){ //all parent nodes are Questions
           var question = new Question(node);
           question.setGuider(this);
           var answers = question.getAnswers();
           for (var j=0; j<answers.length; j++){
               var destnode = answers[j].getDestination();
               if (destnode==null){
                  continue;
               }               
               if (destnode.getID()==target){
                  return question;
               }
           }
        }
    }
    return null;
  }
  this.hasHeader = function(){
    return ( (icon!=null) || (logo!=null) || (introText!=null) || (banner!=null) );
  }

}

//Takes an XMLElement representing the node from the guider xml
function Question(node){

  var thisnode = node;
  var myguider = null;
  var answers  = null;

  this.getText = function(){
    var qtnode = thisnode.getChildByName("question-text");
    return qtnode.getText().replace(/\[.*?:(.*?)\]/g,"$1"); //remove definitions which are not supported in portable guiders
  }
  this.getAnswers = function(){
    if (answers!=null) return answers;
    var answersnode = thisnode.getChildByName("answers");
    var answerelems = answersnode.getChildrenByName("answer");
    var answers = new Array();
    for (var i=0; i<answerelems.length; i++){
        var a = new Answer(answerelems[i]);
        a.setGuider(myguider);
        answers.push(a);
    }
    return answers;
  }
  this.getID = function(){
    return thisnode.getAttribute('id');
  }
  this.hasExplanation = function(){
    return (thisnode.getChildByName("explanation-text")!=null);
  }
  this.getExplanation = function(){
    var exnode = thisnode.getChildByName("explanation-text");
    return exnode.getText();
  }
  this.getGuider = function(){
    return myguider;
  }
  this.hasImages = function(){
    var answers = this.getAnswers();
    for (var i=0; i<answers.length; i++){
        if (answers[i].hasImage()){
           return true;
        }
    }
    return false;
  }
  this.isQuestion     = function(){return true;}
  this.isResult       = function(){return false;}
  this.isGoogleSearch = function(){return false;}
  this.isVideoPage    = function(){return false;}
  this.isBingSearch   = function(){return false;}
  this.isExternalLink = function(){return false;}
  this.isRoot     = function(){
    if (myguider==null){
       alert("question object has no link to the guider.");
       return false;
    }
    if (this.getID()==myguider.getRootQuestion().getID()){
       return true;
    }
    return false;
  }
  this.setGuider  = function(guider){myguider = guider;};
  //parse the XML node

}

function Answer(node){
  this.SUB_NODE      = 1;
  this.GOOGLE_SEARCH = 2;
  this.EXTERNAL_LINK = 3;
  this.BING_SEARCH   = 4;

  var thisnode = node;
  var myguider = null;

  this.getDestination = function(){
    var dest = null;
    var linkselem = thisnode.getChildByName('links');
    if (linkselem!=null){
       var linkelem = linkselem.getChildByName('link');
       if (linkelem != null){ //Then it's an internal link
          var nodeid = linkelem.getAttribute('subsequent-node-id');
          dest = myguider.getNode(nodeid);
       } else { //is it a link to an external guider
          linkelem = linkselem.getChildByName('external-link');
          if (linkelem != null){ //Then it's an external guider
             var linkid = linkelem.getAttribute('guider');
             dest = new ExternalGuider(linkid);
          }
       }
    }
    if (dest!=null){
       dest.setGuider(myguider);
    }
    return dest;
  }

  this.getText = function(){
    var atnode = thisnode.getChildByName("answer-text");
    return atnode.getText().replace(/\[.*?:(.*?)\]/g,"$1"); //remove definitions which are not supported in portable guiders
  }
  this.hasExplanation = function(){
    return (thisnode.getChildByName("explanation-text")!=null);
  }
  this.getExplanation = function(){
    var exnode = thisnode.getChildByName("explanation-text");
    return exnode.getText();
  }
  this.hasImage = function(){
    return (thisnode.getChildByName("image")!=null);
  }
  this.getImage = function(){
    return thisnode.getChildByName("image").getChildByName("url").getText();
  }
  this.getSlug = function(){
    var exnode = thisnode.getChildByName("slug");
    return exnode.getText();
  }
  this.setGuider  = function(guider){myguider = guider;};
}

function Results(node){

  var thisnode = node;
  var myguider = null;

  function htmldecode(str){
    var out = str;
    out = out.replace( /\&amp;/g, '&' );
    out = out.replace( /\&lt;/g, '<' );
    out = out.replace( /\&gt;/g, '>' );
    out = out.replace( /\&quot;/g, '"' );
    out = out.replace( /\&copy;/g, '©' );
    out = out.replace( /\&reg;/g, '®' );
    out = out.replace( /\&laquo;/g, '«' );
    out = out.replace( /\&raqou;/g, '»' );
    out = out.replace( /\&apos;/g, "'" );
    return out;
  }

  this.getID = function(){
    return thisnode.getAttribute('id');
  }
  this.getURL = function(){
    var type  = thisnode.getAttribute('type');
    var query = null;
    switch (type){
      case "GoogleSearch":
           var query = thisnode.getChildByName('query').getText();
           query = "http://www.google.com/search?hl=en&q="+query.replace(/\s/g,"+");
           break;
      case "BingSearch":
           var query = thisnode.getChildByName('query').getText();
           query = "http://www.bing.com/search?q="+query.replace(/\s/g,"+");
           break;
      case "VideoPage":
           var query = thisnode.getChildByName('query').getText();
           query = "http://www.bing.com/search?q="+query.replace(/\s/g,"+");
           break;
      case "ExternalLink":
           var query = thisnode.getChildByName('query').getText();
           break;
    }
    return query;
  }
  this.getContent = function(){
    return htmldecode(thisnode.getChildByName('content').getText());
  }
  this.isQuestion      = function(){return false;}
  this.isResult        = function(){return true;}
  this.isGoogleSearch  = function(){return (thisnode.getAttribute('type')=='GoogleSearch')}
  this.isBingSearch    = function(){return (thisnode.getAttribute('type')=='BingSearch')}
  this.isVideoPage     = function(){return (thisnode.getAttribute('type')=='VideoPage')}
  this.isExternalLink  = function(){return (thisnode.getAttribute('type')=='ExternalLink')}
  this.isSolutionPage  = function(){return (thisnode.getAttribute('type')=='SolutionPage')}
  this.isGuider        = function(){return false;}
  this.setGuider  = function(guider){myguider = guider;};
}

function ExternalGuider(gid){
  var myguider = null;
  var destgid  = gid;
  this.getExternalGID  = function(){return destgid;}
  this.isQuestion      = function(){return false;}
  this.isResult        = function(){return true;}
  this.isGoogleSearch  = function(){return false;}
  this.isBingSearch    = function(){return false;}
  this.isExternalLink  = function(){return false;}
  this.isVideoPage     = function(){return false;}
  this.isSolutionPage  = function(){return false;}
  this.isGuider        = function(){return true;}
  this.setGuider  = function(guider){myguider = guider;};

}