/**

 * ASCIIMath Plugin for TinyMCE editor

 *   port of ASCIIMath plugin for HTMLArea written by 

 *   David Lippman & Peter Jipsen

 *

 * @author David Lippman

 * @copyright Copyright © 2008 David Lippman.

 *

 * Plugin format based on code that is:

 * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.

 */
(function() {
 // Load plugin specific language pack
 tinymce.PluginManager.requireLangPack('asciimath');
 tinymce.create('tinymce.plugins.AsciimathPlugin', {
  /**

		 * Initializes the plugin, this will be executed after the plugin has been created.

		 * This call is done before the editor instance has finished it's initialization so use the onInit event

		 * of the editor instance to intercept that event.

		 *

		 * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in.

		 * @param {string} url Absolute URL to where the plugin is located.

		 */
  init : function(ed, url) {
   var t = this;
   // Register the command so that it can be invoked by using tinyMCE.activeEditor.execCommand('mceAsciimath');
   ed.addCommand('mceAsciimath', function(val) {
    if (t.lastAMnode==null) {
     existing = ed.selection.getContent();
     if (existing.indexOf('class=AM')==-1) { //existing does not contain an AM node, so turn it into one
            //strip out all existing html tags.
            existing = existing.replace(/<([^>]*)>/g,"");
            //replace entities like &lt; with lt.  Not perfect, but better than having
            //the whole entity in there
            existing = existing.replace(/&(.*?);/g,"$1");
            if (val) {
             existing = val;
            }
            entity = '<span class=AMedit>`'+existing+'<span id="removeme"></span>`</span> ';
            if (tinymce.isIE) ed.focus();
            ed.selection.setContent(entity);
            ed.selection.select(ed.dom.get('removeme'));
            ed.dom.remove('removeme');
            ed.selection.collapse(true);
            ed.nodeChanged();
      }
    } else if (val) {
     ed.selection.setContent(val);
    }
   });
   ed.addCommand('mceAsciimathDlg', function() {
    if (typeof AMTcgiloc == 'undefined') {
     AMTcgiloc = "";
    }
    ed.windowManager.open({
     file : url + '/amcharmap.htm',
     width : 630 + parseInt(ed.getLang('asciimathdlg.delta_width', 0)),
     height : 390 + parseInt(ed.getLang('asciimathdlg.delta_height', 0)),
     inline : 1
    }, {
     plugin_url : url, // Plugin absolute URL
     AMTcgiloc : AMTcgiloc
    });
   });
   ed.onKeyDown.add(function(ed, ev) {
    var keycode = ev.keyCode;
    if (keycode==36) { //HOME key
     e = ed.selection.getNode();
     if (t.testAMclass(e)) {
      p = e;
     } else {
      p = ed.dom.getParent(e,t.testAMclass);
     }
     if (p!=null) {
      var par = p.parentNode;
      var el = ed.dom.create("span", {id:'removeme'});
      el.innerText = " ";
      par.insertBefore(el, p);
      ed.nodeChanged();
     }
    }
   });
   ed.onKeyUp.add(function(ed, ev) {
    var keycode = ev.keyCode;
    if (keycode == 36) { //HOME key
     ed.dom.remove('removeme');
    }
   });
   ed.onKeyPress.add(function(ed, ev) {
    var keycode = ev.charCode || ev.keyCode;
    var key = String.fromCharCode(keycode);
    if (key=='`') {
     if (t.lastAMnode == null) {
      existing = ed.selection.getContent();
      if (existing.indexOf('class=AM')==-1) { //existing does not contain an AM node, so turn it into one
             //strip out all existing html tags.
             existing = existing.replace(/<([^>]*)>/g,"");
             entity = '<span class=AMedit>`'+existing+'<span id="removeme"></span>`</span> ';
             if (tinymce.isIE) ed.focus();
             ed.selection.setContent(entity);

             ed.selection.select(ed.dom.get('removeme'));
             ed.dom.remove('removeme');

             ed.nodeChanged();

       }
     }
     if (ev.stopPropagation) {
      ev.stopPropagation();
      ev.preventDefault();
           } else {
      ev.cancelBubble = true;
      ev.returnValue = false;
           }
    }
   });

   // Register asciimath button
   ed.addButton('asciimath', {
    title : 'asciimath.desc',
    cmd : 'mceAsciimath',
    image : url + '/img/ed_mathformula2.gif'
   });

   ed.addButton('asciimathcharmap', {
    title : 'asciimathcharmap.desc',
    cmd : 'mceAsciimathDlg',
    image : url + '/img/ed_mathformula.gif'
   });
   /*

			ed.onInit.add(function(ed) {

					AMtags = ed.dom.select('span.AM');

					for (var i=0; i<AMtags.length; i++) {

						t.nodeToAM(AMtags[i]);

					}

			});

			*/
   ed.onPreInit.add(function(ed) {
    if (tinymce.isIE) {
     addhtml = "<object id=\"mathplayer\" classid=\"clsid:32F66A20-7614-11D4-BD11-00104BD3F987\"></object>";
     addhtml +="<?import namespace=\"m\" implementation=\"#mathplayer\"?>";
     ed.dom.doc.getElementsByTagName("head")[0].insertAdjacentHTML("beforeEnd",addhtml);
    }
   });
   ed.onPreProcess.add(function(ed,o) {
    if (o.get) {
     AMtags = ed.dom.select('span.AM', o.node);
     for (var i=0; i<AMtags.length; i++) {
      t.math2ascii(AMtags[i]);
     }
    }
   });
   ed.onSetContent.add(function(ed,o) {
     AMtags = ed.dom.select('span.AM');
     for (var i=0; i<AMtags.length; i++) {
      t.nodeToAM(AMtags[i]);
     }
   });
   ed.onBeforeExecCommand.add(function(ed,cmd) {
    if (cmd != 'mceAsciimath' && cmd != 'mceAsciimathDlg') {
     AMtags = ed.dom.select('span.AM');
     for (var i=0; i<AMtags.length; i++) {
      t.math2ascii(AMtags[i]);
      AMtags[i].className = "AMedit";
     }
    }
   });
   ed.onExecCommand.add(function(ed,cmd) {
    if (cmd != 'mceAsciimath' && cmd != 'mceAsciimathDlg') {
     AMtags = ed.dom.select('span.AMedit');
     for (var i=0; i<AMtags.length; i++) {
      t.nodeToAM(AMtags[i]);
      AMtags[i].className = "AM";
     }
    }
   });

   ed.onNodeChange.add(function(ed, cm, e) {
    var doprocessnode = true;
    if (t.testAMclass(e)) {
     p = e;
    } else {
     p = ed.dom.getParent(e,t.testAMclass);
    }
    cm.setDisabled('charmap', p!=null);
    cm.setDisabled('sub', p!=null);
    cm.setDisabled('sup', p!=null);
    if (p != null) {
     if (t.lastAMnode == p) {
      doprocessnode = false;
     } else {
      t.math2ascii(p);
      p.className = 'AMedit';
      if (t.lastAMnode != null) {
       t.nodeToAM(t.lastAMnode);
       t.lastAMnode.className = 'AM'
      }
      t.lastAMnode = p;
      doprocessnode = false;
     }
    }
    if (doprocessnode && (t.lastAMnode != null)) { //if not in AM node, process last
         if (t.lastAMnode.innerHTML.match(/`(&nbsp;|\s|\u00a0|&#160;)*`/) || t.lastAMnode.innerHTML.match(/^(&nbsp;|\s|\u00a0|&#160;)*$/)) {
          p = t.lastAMnode.parentNode;
          p.removeChild(t.lastAMnode);
         } else {
          t.nodeToAM(t.lastAMnode);
          t.lastAMnode.className = 'AM';
         }
         t.lastAMnode = null;
          }

   });
   ed.onDeactivate.add(function(ed) {
    if (t.lastAMnode != null) {
         if (t.lastAMnode.innerHTML.match(/`(&nbsp;|\s)*`/)|| t.lastAMnode.innerHTML.match(/^(&nbsp;|\s|\u00a0|&#160;)*$/)) {
          p = t.lastAMnode.parentNode;
          p.removeChild(t.lastAMnode);
         } else {
          t.nodeToAM(t.lastAMnode);
          t.lastAMnode.className = 'AM';
         }
         t.lastAMnode = null;
    }
   });
  },

  /**

		 * Returns information about the plugin as a name/value array.

		 * The current keys are longname, author, authorurl, infourl and version.

		 *

		 * @return {Object} Name/value array containing information about the plugin.

		 */
  getInfo : function() {
   return {
    longname : 'Asciimath plugin',
    author : 'David Lippman',
    authorurl : 'http://www.pierce.ctc.edu/dlippman',
    infourl : '',
    version : "1.0"
   };
  },
  math2ascii : function(el) {
   var myAM = el.innerHTML;
   if (myAM.indexOf("`") == -1) {
    myAM = myAM.replace(/.+(alt|title)=\"(.*?)\".+/g,"`$2`");
    myAM = myAM.replace(/.+(alt|title)=\'(.*?)\'.+/g,"`$2`");
    myAM = myAM.replace(/.+(alt|title)=([^>]*?)\s.*>.*/g,"`$2`");
    myAM = myAM.replace(/.+(alt|title)=(.*?)>.*/g,"`$2`");
    //myAM = myAM.replace(/&gt;/g,">");
    //myAM = myAM.replace(/&lt;/g,"<");
    myAM = myAM.replace(/>/g,"&gt;");
    myAM = myAM.replace(/</g,"&lt;");
    el.innerHTML = myAM;
   }
  },
  nodeToAM : function(outnode) {
    if (tinymce.isIE) {
      var str = outnode.innerHTML.replace(/\`/g,"");
      str.replace(/\"/,"&quot;");
       var newAM = document.createElement("span");
      if (AMnoMathML) {
       newAM.appendChild(AMTparseMath(str));
      } else {
       newAM.appendChild(AMparseMath(str));
      }
      outnode.innerHTML = newAM.innerHTML;
     } else {
      //doesn't work on IE, probably because this script is in the parent
      //windows, and the node is in the iframe.  Should it work in Moz?
     var myAM = outnode.innerHTML; //next 2 lines needed to make caret
     outnode.innerHTML =myAM; //move between `` on Firefox insert math
     AMprocessNode(outnode);
     }
  },
  lastAMnode : null,
  preventAMrender : false,
  testAMclass : function(el) {
   if ((el.className == 'AM') || (el.className == 'AMedit')) {
    return true;
   } else {
    return false;
   }
  }
 });

 // Register plugin
 tinymce.PluginManager.add('asciimath', tinymce.plugins.AsciimathPlugin);
})();
