var TansitionController = Class.create({
  changedNodes: new Array(),
  transitioningCount: 0,
  status: 200,
  bodyClass: "",
  states: {
    READY: "ready",
    LOADING: "loading",
    IN_TRANSITIION: "inTransition"
  },
  styles: {
    // These are needed in Safari as it doesn't pull the correct computed styles for abstract nodes
    HOME_BLOB: "125px",
    TECH_BLOB: "210px",
    DESIGN_BLOB: "80px",
    APPROACH_BLOB: "165px",
    CONTACT_BLOB: "10px",
    CASE_BLOB: "10px"
  },
  initialize: function() {
    // Override all internal links
    this.overrideAllInternalLinks();
    this.ajaxLoader.initialize();
    var url = location.href;
    var relativeLocation = (url.include(location.host)? url.split(location.host)[1] : url).split("#")[0];
    relativeLocation = relativeLocation.endsWith("/")? relativeLocation+="index.html": relativeLocation;
    if(url.endsWith("#")) location.href = relativeLocation;
    this.navigation.history.push(relativeLocation);
    if(!location.href.include("#"))this.trackPage(relativeLocation);
    
    this.transition = new Tansition();
    this.transition.observe("transition:complete",function(ev){
      this.overrideAllInternalLinks(ev.response);
    }.bind(this));
    
    this.transition.observe("transition:start",function(){
      this.currentState = this.states.IN_TRANSITIION;
    }.bind(this));
    
    this.transition.observe("transition:finish",function(ev){
      this.transitionHandler();
    }.bind(this));
    function filter(n) {
      try {
        n.updated = false;
      } catch(e) {
        //console.error("Updated not valid "+e.message);
      }
      if(n.nodeType == 1 && n.hasClassName("watch")) return true;
      return false;
    }
    this.currentDocument = new meld.utilities.TreeWalker(document.body, filter, true);
    this.interval.start.bind(this)();
    this.currentState = this.states.READY;
  },
  
  transitionHandler: function(){
   
    if(--this.transitioningCount == 0){
      this.overrideAllInternalLinks();
      this.currentState = this.states.READY;
      document.fire("document:pageLoaded",{url:this.navigation.history.last(),status:this.status});
    }
  },
  
  trackPage: function(url){
    if(typeof(url) == 'undefined') url = document.location.href;
    this.trackGa(url);
    this.trackOmniture(url);
  },
  
  trackOmniture: function(destURL){
    window.trackOmniture(destURL);
  },
  
  trackGa: function(url){
    try{
      //console.info("Tracking url: " + url);
      var pageTracker = _gat._getTracker("UA-6139629-1");
      var pageTracker2 = _gat._getTracker("UA-291924-35");
      // Strip the domain from the url
      url = url.replace("http://"+window.location.host, "");

      pageTracker._trackPageview(url);
      pageTracker2._trackPageview(url);      
    } 
    catch(err){
      //console.warn('Caught exception tracking url: ' + url);
    }
  },
  
  overrideAllInternalLinks: function() { 
    this._initLinkTracking();
    var anchors = $$('body a'); 
    for(var i=0; i<anchors.length;i++) {
      var a = $(anchors[i]);
      if(a.href.indexOf(window.location.hostname) >= 0 &&
         !a.hasClassName("ignore") &&
         !a.hasClassName("enlarge") &&
         a.href.endsWith(".html") &&
         !a.hasClickObserver) { 
        a.observe("click",window.trackOmniLink);
        a.observe("click", this.linkClickHandler.bind(this));
        a.hasClickObserver = true;
      };
    }
    
  },

  _initLinkTracking: function(){
    
    function _processAndGetText(str){
      str = str.replace(/<[^>]*>/,"");
      var text = str.strip().toLowerCase();
 
      text = text.replace(/[©.,@#\'\"]/g, "").strip().replace(/\ /g, "_");
      if(text.length>30) text = text.substr(0,25);
      return text;
    };
    
    

    
    $$("a").each(function(item){

      var href = item.href;
      
      if (href != "#" && href.strip().lengrh != 0) {
   
        var text = _processAndGetText(item.innerHTML);
        
        if (text.length != 0) {
          
          if(item.name.length==0){

            var title = _processAndGetText(item.title);

            text = title;

            var name = "&lid="+text;
           // console.info(name);
           // $(this).attr("name",name);
           // this.setAttribute("name",name);
           // this.name=name;
           // this was the only way to make it work in IE6,7
            var tempA = item.cloneNode(true);
            tempA.setAttribute("name",name);
            Element.replace(item,tempA);
            
          }
          var item = this;

          
        }else{

        }
      }
    });
    
    
  },
  

  linkClickHandler: function(event) {
    event.stop();
    var a = event.target;
    while(a.nodeName.toLowerCase() != "a") {
      a = a.parentNode;
    }
    if(a.parentNode.id == "case-study-nav") {
      this.interval.stop.bind(this)();
    } else {
      this.interval.stop.bind(this)();
      this.interval.start.bind(this)();
    }
    this.navigation.loadPage.bind(this)(a.href);
  },

  imageLinkClickHandler: function(event) {
    event.stop();
    var a = $(event.target);
    while(!a.hasAttribute("href")) {
      a = a.parentNode;
    }

    // This is so Google doesn't index the easter egg
    if(a.nodeName.toLowerCase() == "area") a.href = a.alt;

    this.iv.changeImage(a.href);
    this.iv.show();
  },

  handleFormSubmit: function(event) {
    event.stop();
    if(event.element().validator.isFormValid())
      {
        var url = event.element().action + "?" + event.element().serialize(false);
        this.navigation.loadPage(url);
      }
  },

  ajaxLoader: {
    initialize: function() {
  /*    this.container = new Element("img",{"src":contextPath+"/base/images/progress-running.gif"});
      this.container.id = "ajax-loader";
      this.container.className = "ajax-loader";
      this.container.style.display = "none";*/
      this.container = new Element("div");
      this.container.id = "ajax-loader";
      this.container.className = "ajax-loader";
      this.container.innerHTML = "Loading...";
      this.container.style.display = "none";
      
      document.body.appendChild(this.container);

      document.observe("mousemove", (function(ev) {
            this.container.style.top = ev.pointerY()+10+"px";
            this.container.style.left = ev.pointerX()+10+"px";
          }).bind(this));
    },
    show: function() {
      this.container.show();
    },
    hide: function() {
      this.container.hide();
    }
  },

  interval: {
    start: function() {
      this.interval.timer = setInterval(this.interval.handleTimer.bind(this), (30*1000));
    },
    stop: function() {
      clearInterval(this.interval.timer);
    },
    handleTimer: function(ev) {
      if(this.navigation.history.last().toString().match(/our\-work|services/)) {
        meltmedia.segmentstudy.nextSegment();
      } else {
        this.interval.stop.bind(this)();
      }
    }
  },

  utility: {
    toXML: function(string) {
      try { 
        /* firefox 3.6. doesn't throw an error so it needs to be forced to do that */
        if(typeof ActiveXObject == "undefined") throw 'ActiveXObject is undefined';
        var parser = new ActiveXObject("Microsoft.XMLDOM");
        parser.async = "false";
        parser.loadXML(string);
        if(parser.parseError.errorCode != "0") {
          /*
            console.info("Error Code: "+parser.parseError.errorCode + "\n" +
            "Error Reason: "+parser.parseError.reason + "\n" +
            "Error Line: "+parser.parseError.line);
          */
        }
        return parser;
      } catch (e) { 
        var parser = new DOMParser();
        return parser.parseFromString(string, "text/xml");
      }

      return false;
    },

    elementsMatch: function(newElement, oldElement) {
      var x, y;

      if(newElement.nodeType == 3 && oldElement.nodeType == 3) {
        x = newElement.nodeValue.toString().replace(/[\t\r\n\s]/g, "");
        y = oldElement.nodeValue.toString().replace(/[\t\r\n\s]/g, "");
      } else {
        x = newElement.innerHTML.toString().replace(/[\t\r\n\s]/g, "");
        y = oldElement.innerHTML.toString().replace(/[\t\r\n\s]/g, "");
      }

      return (x == y);
    },

    attributesMatch: function(newElement, oldElement) {
      if(newElement.nodeType == 3 && oldElement.nodeType == 3) return true;

      if(newElement.attributes.length == oldElement.attributes.length) {
        for(var i=0;i<newElement.attributes.length;i++) {
          var nAttr = newElement.attributes[i];
          if(oldElement.hasAttribute(nAttr.nodeName)) {
            if(oldElement.getAttribute(nAttr.nodeName) != nAttr.nodeValue) {
              return false;
            }
          } else {
            return false;
          }
        }
      } else {
        return false;
      }

      return true;
    },

    updatePage: function(node) {
      var preventDefault = false;
      this.changedNodes = [];
      this.transitioningCount = 0;

      // We need to make sure the transition has happened on the nav-main first
      this.newBodyClass = node.getAttribute("class");

      function filter(n) {
        // We only want element nodes with the class name watch
        if(n.nodeType == 1 && n.hasClassName("watch")) return true;
        return false;
      }
            
      var xmlWalker = new meld.utilities.TreeWalker(node, filter, true);
      this.transitioningCount = xmlWalker.nodeList.length;
      for(var i=0;i<xmlWalker.nodeList.length;i++) {
     
        var nNode = xmlWalker.nodeList[i];
        var oNode = $(nNode.id);
        
        if(oNode == null || !oNode.hasClassName('watch')){
          this.transitionHandler();
          continue;
        }
        
        var watchers = $$("#"+oNode.id+" .watch");
        if(watchers.length>0){ 
          var nNodeXmlWalker = new meld.utilities.TreeWalker(nNode, filter, true);
          if(nNodeXmlWalker.nodeList.length==watchers.length){
            this.transitionHandler();
            continue;
          }else{
            watchers.each(function(el){el.removeClassName('watch');});
          }
          delete nNodeXmlWalker;
        }
        


        if(oNode.innerHTML!=nNode.innerHTML){
          
             switch(nNode.id) {
             case "content":
               this.transition.fade(oNode, nNode);
             break;

             case "flash-header":
               this.transition.fade(oNode, nNode);
             break;

             default:
               this.transition.pSwap.bind(this.transition)(oNode, nNode);
             }
          
        }else{
          this.transitionHandler();
        }
        
      }

      delete xmlWalker;

    }
  },

  navigation: {
    history: new Array(),

    loadPage: function(url) {
      var url = url.split("?")[0];
      if(this.currentState == this.states.READY && 
         this.navigation.history.last() != url &&
         !this.navigation.history.last().endsWith(url)) {
           
        this.ajaxLoader.show();
        this.currentState = this.states.LOADING;
        this.navigation.trackHistory.bind(this)(url);
        this.currentDocument.update(); 
        
        new Ajax.Request(url, {
            method: "get",
            
            
            onComplete: function(transport){
            
              this.ajaxLoader.hide();

              this.status = transport.status;
              if(transport.status!=200){
                s.pageType = "errorPage";
              }else{
                s.pageType = "";
              }
              this.trackPage(url);
              
              this.navigation.handlePageLoad.bind(this)(transport);
              
            }.bind(this),
            
            
            onFailure: function(){
              
            }.bind(this)
        });
      }
    },

    handlePageLoad: function(transport,url) {
      var responseContent = transport.responseText.replace(/[\t\r\n]/g, "");
      document.title = responseContent.match(/<title\b[^>]*>(.*?)<\/title>/)[1].toString(); 
      
      var responseContentXML = this.utility.toXML(responseContent.match(/<body\b[^>]*>.*?<\/body>/).toString());
      
      //replacing the all meta data
/*

      $$("meta").each(function(item){
        $$("head")[0].removeChild(item);
      });
      
      responseContent.match(/<meta\b[^>]* \/>/g).each(function(meta){
        var metaEl = this.utility.toXML(meta).firstChild;
        $$("head")[0].appendChild(metaEl);
      }.bind(this)); 
*/

      
      previousSection = document.body.className.split(" ")[0];
      //setting the class for flash container
      for(var i=0;i<2;i++){
        $("flash-container").removeClassName("pre-state"+i);
      };
      $("flash-container").addClassName("pre-"+document.body.className.split(" ")[1]);
      //setting a calss to body
      $$("body")[0].className = responseContentXML.firstChild.getAttribute('class');
     // this.bodyClass = responseContentXML.firstChild.getAttribute('class');
      //bundleName = 'patient/'+document.body.className.split(" ")[0];
      
      section = document.body.className.split(" ")[0];
      // We need to run through the response fragment and see what's different from our current state
      this.utility.updatePage.bind(this)(responseContentXML.firstChild);
    },

    trackHistory: function(url) {
      if(this.navigation.history.last() != url) {
        this.navigation.history.push(url);
      }
    }
  }


});
