var BBCode = new Class({
  elementId: false,
  container: false,
  bbcodeURL: "/forum/json/bbcode.html",
  bbcodeTags: {
    "bold": "b", "italic": "i", "underline": "u", "strike": "s", "quote": "quote", "url": "url",
    "red": "color", "yellow": "color", "green": "color", "blue": "color", "purple": "color", "black": "color"
  },
  _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",


  initialize: function () { },
  
  load: function ()
  {
    var me = this;
    var elements = $(document.body).getElements("textarea.bbcode");
    elements.each(function (element) { me.createEditor(element); });
  },

  createEditor: function ( element )
  {
    var divElement = new Element("div", {
      "id": element.name+"Container",
      "class": "bbcodeContainer"
    });
    this.container = divElement;
    this.elementId = element.id = element.name;
    divElement.setStyle("width", "455px");
    element.setStyle("width","445px");

    var buttons = this.createButtons();
    var preview = this.createPreview();

    divElement.injectAfter(element);
    divElement.appendChild(element);
    divElement.appendChild(buttons);
    divElement.appendChild(preview);
  },

  createButtons: function ()
  {
    
    var buttons = new Element("div", {"class": "bbcodeButtons"});

    var bold = this.createButton("bold", "<b>B</b>",40); buttons.appendChild(bold);
    var italic = this.createButton("italic", "<i>I</i>",40); buttons.appendChild(italic);
    var underline = this.createButton("underline", "<u>U</u>",40); buttons.appendChild(underline);
    var strike = this.createButton("strike", "<s>S</s>",40); buttons.appendChild(strike);
    var quote = this.createButton("quote", "Quote",55); buttons.appendChild(quote);
    var url = this.createButton("url", "URL",50); buttons.appendChild(url);

    var red = this.createColor("red"); buttons.appendChild(red);
    var yellow = this.createColor("yellow"); buttons.appendChild(yellow);
    var green = this.createColor("green"); buttons.appendChild(green);
    var blue = this.createColor("blue"); buttons.appendChild(blue);
    var purple = this.createColor("purple"); buttons.appendChild(purple);
    var black = this.createColor("black"); buttons.appendChild(black);

    return buttons;
  },

  createPreview: function ( )
  {
    var preview = new Element("div", {"class": "bbcodePreview"});
    var previewContainer = new Element("div", {
      "class": "bbcodePreviewContainer",
      "id": this.elementId+"Preview",
      "styles": {
        "position": "absolute",
        "display": "none",
        "text-align": "left"
      }
    });
    var anchor = new Element("a", {
      "href": "javascript:bbcode.showPreview('"+this.elementId+"');"
    });

    var pos = $(this.elementId).getCoordinates();
    previewContainer.setStyle("left", (pos.left+pos.width+5) + "px");

    anchor.innerHTML = "preview";
    preview.appendChild(anchor);
    this.container.appendChild(previewContainer);

    $(this.elementId).addEvent("keyup", function () { $(this.id+"Preview").setStyle("display","none"); });
    return preview;
  },

  createButton: function (type, html, buttonWidth)
  {
    var button = new Element("button", { 
      "type": "button",
      "events": { 
        "click": function () { bbcode.click(this, type); } 
      } 
    });

    if (buttonWidth) button.setStyle("width",buttonWidth+"px");
    button.elementId = this.elementId;
    button.innerHTML = html;
    return button;
  },

  createColor: function ( type )
  {
    var className = "color"+type.charAt(0).toUpperCase()+type.substr(1, type.length-1);
    var color = new Element("div", { 
      "class": "bbcodeColor "+className,
      "events": {
        "click": function () { bbcode.click(this, type); }
      }
    });
    color.elementId = this.elementId;
    return color;
  },

  click: function ( element, type )
  {
    switch (type) {
      case "red": case "yellow": case "green": case "blue": case "purple": case "black":
        var startTag = "["+eval("this.bbcodeTags."+type)+"="+type+"]";
      break;
      default:
        var startTag = "["+eval("this.bbcodeTags."+type)+"]";
      break;
    }
    var endTag = "[/"+eval("this.bbcodeTags."+type)+"]";

    switch (type) {
      case "url": 
        var argument = false;
        var val = this.getSelection($(element.elementId));
        if (val.substr(0,7) == "http://") {
          argument = val;
        } else {
          argument = prompt("Voer de URL in:","http://");
        }
        startTag = "[url="+argument+"]";
      break;
    }

    this.addTag(startTag, endTag, $(element.elementId));
  },

  getSelection: function ( element )
  {
    //IE support
    if (document.selection) {
      element.focus();
      sel = document.selection.createRange();
      return sel.text;
    } else if (element.selectionStart || element.selectionStart == '0') {//MOZILLA/NETSCAPE support
      var startPos = element.selectionStart;
      var endPos = element.selectionEnd;
      return element.value.substr(startPos, endPos-startPos);
    }
    return false;
  },

  addTag: function ( startTag, endTag, element )
  {
    //IE support
    if (document.selection) {
      element.focus();
      sel = document.selection.createRange();
      var val = sel.text;
      sel.text = startTag+val+endTag;
    } else if (element.selectionStart || element.selectionStart == '0') {//MOZILLA/NETSCAPE support
      var startPos = element.selectionStart;
      var endPos = element.selectionEnd;
      var val = element.value.substr(startPos, endPos-startPos);
      element.value = element.value.substr(0,startPos)+
                      startTag+val+endTag+
                      element.value.substr(endPos);
      element.selectionStart = startPos+startTag.length;
      element.selectionEnd = endPos+startTag.length;
    } else {
      element.value += startTag + " " + endTag;
    }
    element.focus();
  },

  showPreview: function ( id )
  {
    var input = $(id).value;
    input = this.uuencode(input);
    var sendObject = {"bbcode": input};
    var me = this;
    var callback = function( data ) { $(id+"Preview").setStyle("display",""); $(id+"Preview").innerHTML = data.html; }
    var json = new Json.Remote( this.bbcodeURL, { onComplete: callback, method: 'POST' } );
    json.send(sendObject);
  },

  uuencode : function (input)
  {
    var output = "";
    var chr1, chr2, chr3;
    var enc1, enc2, enc3, enc4;
    var i = 0;

    input = this._utf8_encode(input);

    do {
      chr1 = input.charCodeAt(i++);
      chr2 = input.charCodeAt(i++);
      chr3 = input.charCodeAt(i++);

      enc1 = chr1 >> 2;
      enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
      enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
      enc4 = chr3 & 63;

      if (isNaN(chr2)) {
          enc3 = enc4 = 64;
      } else if (isNaN(chr3)) {
          enc4 = 64;
      }

      output = output + this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) + this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
    } while (i < input.length);

    return output;
  },

  _utf8_encode : function ( str )
  {
    str = str.replace(/\r\n/g,"\n");
    var utftext = "";

    for (var n = 0; n < str.length; n++) {
      var c = str.charCodeAt(n);
      if (c < 128) {
        utftext += String.fromCharCode(c);
      } else if((c > 127) && (c < 2048)) {
        utftext += String.fromCharCode((c >> 6) | 192);
        utftext += String.fromCharCode((c & 63) | 128);
      } else {
        utftext += String.fromCharCode((c >> 12) | 224);
        utftext += String.fromCharCode(((c >> 6) & 63) | 128);
        utftext += String.fromCharCode((c & 63) | 128);
      }
    }
    return utftext;
  }
});

var bbcode;
window.addEvent("domready", function() { bbcode = new BBCode(); bbcode.load(); });

