var Glossary = Class.create({

  _openItem: null,
  _context: null,
  _currentActiveNum: null,
  _isActive: false,
  _terms: null,
  _store: [],

  initialize: function(context) {
    this._context = context;
    var session = context.getCookie();
    if(session) {
      this._isActive = session.isActive;
    }

    this._activateControls();

    if(this._isActive) {
      this._activateGlossary();
    }
    this.setGlossaryIitemLinks();
  },

  _activateControls: function() {
      var els = $("glossary-control").getElementsByTagName("a");
      $("glossary-control").removeClassName("hide");
      for(var i=0;i<els.length;i++) {
        var el = $(els[i]);
        if(this._isActive) {
          if(el.id == "glossary-on") {
            el.addClassName("highlight");
          }
        } else {
          if(el.id == "glossary-off") {
            el.addClassName("highlight");
          }
        }
        el.observe("click", this.toggle.bind(this));
      }
      this._controls = els;
  },

  _loadTerms: function() {
    this._terms = [];

    new Ajax.Request(contextPath+subPath+"/patient/"+".glossary.json?terms=/apps/avastin/base/patient/glossary/terms", {
        method: "GET",
        onSuccess: function(transport) {
          this._terms = transport.responseJSON;
          this.initTerms();
        }.bind(this)
    });

  },
  
  refresh: function(){
    if(this._isActive) {  
       this._activateGlossary();
    } 
    this.setGlossaryIitemLinks();
  },
  // this method is for glossary alphabet links
  setGlossaryIitemLinks: function(){
    $$('#find-item a, a[href="#find-item"]').each(function(el){
      el.addClassName("ignore");
      el.observe("click",function(ev){
        ev.stop();
        var tg = $(this.href.split("#")[1]);
        if(tg!=null)tg.scrollTo();
      });
    });

  },
  
  toggle: function(event) {
    event.preventDefault(); 
    for(var i=0;i<this._controls.length;i++) { 
      if(this._controls[i].hasClassName("highlight")) {
        this._controls[i].removeClassName("highlight");
      } else {
        this._controls[i].addClassName("highlight");
      }
    }

    this._isActive = (this._isActive) ? false : true;

    if(this._isActive) {
      this._activateGlossary();
    } else {
      this._deactivateGlossary();
    }
  },

  _activateGlossary: function() {
      if(this.getTerms()) {
        this.initTerms();
      };
      this._context.setCookie({"isActive": true});
  },

  _deactivateGlossary: function() {
    for(var i=0;i<this._store.length;i++) {
      var node = this._store[i];
      var t = node.innerHTML;
      node.insert({ after: t});
      var pn = node.parentNode;
      var ih = "";
      node.remove();
      var cn = pn.childNodes[0];
      var nodeTotal = pn.childNodes.length;
      var textTotal = 0;
      while(cn) {
        if(cn.nodeType === 3) {
          textTotal++;
          ih += cn.nodeValue;
        }
        cn = cn.nextSibling;
      }

      /** This is done to reset the segmentation that happens when inserting nodes */
      if(textTotal === nodeTotal) {
        pn.innerHTML = ih;
      }
    }

    if(this._openItem) {
      this._openItem.box.dialog('close');
    }
    this._context.setCookie({"isActive": false});
  },

  getTerms: function() {
    if(this._terms === null) this._loadTerms();
    return this._terms;
  },
  
  initEvents: function(){
    var items = this._store = $$("em.glossary-item");
    items.each(function(item){
      item.observe("mouseover",this.showTimer.bind(this));
      item.observe("mouseout",function(){ clearInterval(this.timer); }.bind(this))
    }.bind(this));
  },

  initTerms: function() {
    var terms = this.getTerms();
    if(terms.length == 0) return;
    if($("content")==null)return;
    var content = $("content");
    var termNum = 0;

    var termList = "";

    terms.each(function(term){
      if(term === undefined) return;
      var variants = term.variants.split(",");
      for(var i=0;i<variants.length;i++) {
        termList += variants[i]+"|";
      }
    });

    if(termList === "") return;
    termList = termList.substring(0, termList.length-1);

    var reg = new RegExp("\\b\("+termList+"\)\\b","gim");
    var nodes = this.getMatchingNodes(content, reg);

    try {
      nodes.each(function(node) {
        termNum = 0;
        terms.each(function(term) {
         if(!term) return;
          var variants = term.variants.split(",");
          for(var i=0;i<variants.length;i++) {
            var rep = new RegExp("\\b\("+variants[i]+"\)\\b","gim");
            var exec = new RegExp("\\b\("+variants[i]+"\)\\b","im");
            if(node.innerHTML && node.innerHTML.match(exec)) {
              var cns = node.childNodes;
              for(var j=0;j<cns.length;j++) { 
                var n = cns[j]; 
                if(n.nodeType === 3 && n.nodeValue.match(exec)) {
                  var m = exec.exec(n.nodeValue)[1];
                  var text = n.nodeValue.split(m);
                  var pn = n;
                  for(var x=0;x<text.length;x++) {
                    var tn = jq$(document.createTextNode(text[x]));
                    tn.insertAfter(pn);
                    if(x+1!=text.length) { 
                      var em = jq$("<em class='glossary-num-"+termNum+" glossary-item'>"+m+"</em>");
                      tn.after(em);
                      pn = em;
                    } else {
                      pn = tn;            
                    }
                  }
                  jq$(n).remove();
                }
              }

              /*
              var text = exec.exec(node.innerHTML)[1];
              node.innerHTML = node.innerHTML.replace(rep, "<em class='glossary-num-"+termNum+" glossary-item'>"+text+"</em>");
               */
            }
          }
          termNum++;
        });
      });
    } catch(e) {
      //console.error(e.message);
    }

    this.initEvents();
  },

  getMatchingNodes: function(node, pattern) {
      var nodes = node.childNodes;
      var ret = []; 
      try {
        for(var i=0;i<nodes.length;i++) {
          var n = nodes[i];

          if(n.nodeType == 3 && n.nodeValue.match(pattern)) {
            ret.push(n.parentNode);
          }

          if(node.childNodes && node.childNodes.length > 0) {
            var mn = this.getMatchingNodes(n, pattern);
            if(mn.length > 0) ret = ret.concat(mn);
          }

        }
      } catch(e) {
        ////console.error(e.message);
      }

      return ret;
  },
  
  showTimer: function(ev){
    var num = 0;
    /**
       Due to the way IE handles events we need to store a local copy of the event
       because by the time the timer executes the method call our event is gone.
       Ref: http://javascriptfixer.com/member-not-found.php
     */
    var evt = {};
    for(var k in ev) evt[k] = ev[k];
    if(typeof this.timer!= undefined) clearInterval(this.timer);
    this.timer = setInterval(function(){
      num++;
      if (num == 3) {
        this.showDef(evt);
        clearInterval(this.timer);
      }
    }.bind(this),300);
  },
  
  showDef: function(ev){ 
    var el = ev.findElement("em");
    if (this._openItem == null || this._openItem.el != el) {
      if(this._openItem!=null)this._openItem.box.dialog('close');
      var num = parseInt(el.className.split("glossary-num-")[1].split(" ")[0].strip());
      var term = this.getTerms()[num];
      var defBox = new Element("div",{"id":"glossary-dialog-content"});
      var defBoxContent = new Element("div");
      var content = new Element("p").update(term.definition);
      defBox.appendChild(defBoxContent);
      //defBox.appendChild(content);
      defBoxContent.appendChild(content);
      document.body.appendChild(defBox);
      var _this = this;2
      function onClose(evt, ui){ 
        _this._openItem = null;
      };
      
      /*
      var config = {
        containerCls: "glossary-modal",
        modal: false,
        draggableCls: "glossary-modal-header",
        cls: "glossary-modal-body",
        width: 420,
        killOnHide: true,
        closeBtnCls: "glossary-close-btn",
        top: ev.pageY + 10,
        left: ev.pageX - 100,
        onHide: onHide.bind(this),
        header: {
          cls: "glossary-modal-header",
          text: "<p>" + term.name + "</p><span class='glossary-close-btn'>close</span>"
        }
      };
      */

      //var dialog = new Dialog(defBox, config);
      var dialog = jq$(defBox).dialog({
          minHeight: 0,
          height: 'auto',
          width: 350,
          title: term.name,
          resizable: false,
          position: 'center',
          close: onClose
        });

      dialog.dialog('open');
      this._openItem = {
        num: num,
        box: dialog,
        el: el
      };
    }
  }
  
});

