/*
  PFrameworkCS API

  Copyright (C) 2004 by Jernej Kos <kostko@jweb-network.net>
  Copyright (C) 2004 by Gregor Kalisnik <gregor@unimatrix-one.org>
  Copyright (C) 2004 by Unimatrix-One (www.unimatrix-one.org)

  This javascript is part of the PFramework CMS system. Any unauthorised
  use outside of this system is strictly prohibited.
*/

var BBEditor = Class.create({
  initialize: function(editorId, id, disable, embedded)
  {
    var thisVar = this;

    var editor = $(editorId);
    this.id = editor.id.replace('editor', '') + id;
    this.editor = editor;

    if (disable == undefined)
      disable = true;

    if (embedded == undefined)
      embedded = true;

    editor.id = editor.id + id;

    var childs = editor.descendants();

    for (var i = 0; i < childs.length; i++) {
      if (childs[i].tagName == 'DIV' || childs[i].tagName == 'TEXTAREA' || childs[i].tagName == 'SPAN') {
        if (childs[i].tagName == 'TEXTAREA' && disable)
        childs[i].disable();
        else if(childs[i].tagName == 'TEXTAREA')
        childs[i].enable();

        if (childs[i].id == 'editorButtons' || childs[i].id == 'editorStatusButtons') {
          if (childs[i].id == 'editorStatusButtons' && !embedded) {
            childs[i].hide();
            childs[i].id = '';
            continue;
          } else {
            childs[i].id = childs[i].id + this.id;
          }
          var hrefs = childs[i].getElementsByTagName('LI');
          for (var j = 0; j < hrefs.length; j++) {

            var clickFunction;
            switch (hrefs[j].className) {
              case 'italicButton' :
                  clickFunction = function () {
                    thisVar.addItalic();
                  };
                  break;
              case 'boldButton' :
                  clickFunction = function () {
                    thisVar.addBold();
                  };
                  break;
              case 'underlineButton' :
                  clickFunction = function () {
                    thisVar.addUnderline();
                  };
                  break;
              case 'strikethroughButton' :
                  clickFunction = function () {
                    thisVar.addStrikethrough();
                  };
                  break;
              case 'colorButton' :
                  hrefs[j].addClassName('colorLayer' + this.id + 'Toggle');
                  continue;
                  break;
              case 'imgButton' :
                  clickFunction = function () {
                    thisVar.addImg();
                  };
                  break;
              case 'urlButton' :
                  hrefs[j].addClassName('urlLayer' + this.id + 'Toggle');
                  continue;
                  break;
              case 'urlOldButton' :
                  clickFunction = function () {
                    thisVar.addUrlOld();
                  };
                  break;
              case 'leftJustifyButton' :
                  clickFunction = function () {
                    thisVar.addParagraph('left');
                  };
                  break;
              case 'rightJustifyButton' :
                  clickFunction = function () {
                    thisVar.addParagraph('right');
                  };
                  break;
              case 'centerJustifyButton' :
                  clickFunction = function () {
                    thisVar.addParagraph('center');
                  };
                  break;
              case 'fullJustifyButton' :
                  clickFunction = function () {
                    thisVar.addParagraph('justify');
                  };
                  break;
              case 'header1Button' :
                  clickFunction = function () {
                    thisVar.addH(1);
                  };
                  break;
              case 'header2Button' :
                  clickFunction = function () {
                    thisVar.addH(2);
                  };
                  break;
              case 'header3Button' :
                  clickFunction = function () {
                    thisVar.addH(3);
                  };
                  break;
              case 'releaseButton' :
                  clickFunction = function () {
                    thisVar.addTags('[release]', '[/release]');
                  };
                  break;
              case 'emoButton' :
                  clickFunction = function () {
                    thisVar.toggleEmotions();
                  };
                  break;
              case 'smiliesButton' :
                  clickFunction = function () {
                    thisVar.toggleEnabledEmotions();
                  };
                  break;
              case 'unistorageButton' :
                  var fileManagerHandler = this.registerFileManager.bindAsEventListener(this);
                  hrefs[j].observe('click', fileManagerHandler);
                  continue;
                  break;
              default :
                clickFunction = function() {
                };
                break;
            }

            hrefs[j].observe('click', clickFunction);
          }
          continue;
        }

        if (childs[i].id == 'editorEmotions') {
          var hrefs = childs[i].select('img');
          hrefs.each(function (item) {
            var emotion = item.readAttribute('alt');
            item.observe('click', (function(e, emotion) {return function() {thisVar.addEmotion(emotion);};})(this, emotion));
          })
        }

        childs[i].id = childs[i].id + this.id;
      }
    }

    if ($('urlLayer' + this.id) != undefined) {
      this.urlLayer = new PLayer('urlLayer' + this.id);
      var clickHandler = this.addUrl.bindAsEventListener(this);
      this.editor.select('.urlLayer' + this.id + 'Toggle')[0].observe('click', clickHandler);
      $('urlLayer' + this.id).select('.insertButton')[0].observe('click', clickHandler);
    }

    if ($('colorLayer' + this.id) != undefined) {
      this.colorLayer = new PLayer('colorLayer' + this.id);
      this.editor.select('.colorLayer' + this.id + 'Toggle')[0].observe('click', this.urlLayer.hide.bindAsEventListener(this.urlLayer));
      var clickHandler = this.addColor.bindAsEventListener(this);
      $('colorLayer' + this.id).select('.insertButton')[0].observe('click', clickHandler);
      var colorTiles = $('colorLayer' + this.id).select('.colorTile');
      for (var i = colorTiles.length - 1; i >= 0; i--) {
        colorTiles[i].observe('click', clickHandler);
      }
    }

    var panel = $('editorPanel' + this.id);
    if (panel != undefined) {
      this.resizeHandler = this.resizeEditor.bindAsEventListener(this);
      panel.observe('mousedown', function()
      {
        /* IE */
        $('body').onselectstart = function() {return false;};
        /* Non-IE */
        $('body').onmousedown = function() {return false;};
        document.observe('mousemove', thisVar.resizeHandler);
      });

      document.observe('mouseup', function()
      {
        /* IE */
        $('body').onselectstart = function() {};
        /* Non-IE */
        $('body').onmousedown = function() {};
        document.stopObserving('mousemove', thisVar.resizeHandler);
      });
    }

    var leftButton = this.editor.select('.editorLeft')[0];
    var rightButton = this.editor.select('.editorRight')[0];
    if (leftButton == undefined || rightButton == undefined)
      return;
    var moveLeftHandler = this.moveLeft.bindAsEventListener(this);
    var moveRightHandler = this.moveRight.bindAsEventListener(this);
    var flipLeftHandler = this.flipLeft.bindAsEventListener(this);
    var flipRightHandler = this.flipRight.bindAsEventListener(this);
    leftButton.observe('mouseover', moveLeftHandler);
    leftButton.observe('mouseout', (function (thisVar) {return function() {clearTimeout(thisVar.moveTimer);};})(this));
    leftButton.observe('click', flipLeftHandler);
    rightButton.observe('mouseover', moveRightHandler);
    rightButton.observe('mouseout', (function (thisVar) {return function() {clearTimeout(thisVar.moveTimer);};})(this));
    rightButton.observe('click', flipRightHandler);
  },

  enable: function()
  {
    $('editorArea' + this.id).enable();
  },

  disable: function()
  {
    $('editorArea' + this.id).disable();
  },

  getValue: function()
  {
    return $('editorArea' + this.id).value;
  },

  setValue: function(text)
  {
    $('editorArea' + this.id).setValue(text);
  },

  setPreviewOutput: function(id)
  {
    this.previewId = id;
  },

  removeSelected: function()
  {
    var editorArea = $('editorArea' + this.id);
    var start = editorArea.getValue().substring(0, editorArea.selectionStart);
    var end = editorArea.getValue().substring(editorArea.selectionEnd, editorArea.getValue().length);
    editorArea.setValue(start + end);
  },

  add: function(text)
  {
    insert_text(text, $('editorArea' + this.id));
  },

  /* Code in this method is a modified one from phpBB */
  addTags: function(startTag, endTag, example)
  {
    theSelection = false;

    var editor = $('editorArea' + this.id);

    editor.focus();

    if (document.selection && document.selection.createRange) {
      theSelection = document.selection.createRange().text;

      if (theSelection) {
        document.selection.createRange().text = startTag + theSelection + endTag;
        editor.focus();
        theSelection = '';
        return;
      }
    } else if (editor.selectionEnd && (editor.selectionEnd - editor.selectionStart > 0)) {
      mozWrap(editor, startTag, endTag);
      editor.focus();
      theSelection = '';
      return;
    }

    var caret_pos = getCaretPosition(editor).start;
    var new_pos = caret_pos + startTag.length;

    insert_text(startTag + endTag, editor);

    if (!isNaN(editor.selectionStart)) {
      editor.selectionStart = new_pos;
      editor.selectionEnd = new_pos;
    } else if (document.selection) {
      var range = editor.createTextRange();
      range.move("character", new_pos);
      range.select();
      storeCaret(editor);
    }
  },

  selection: function()
  {
    var editor = $('editorArea' + this.id);
    return editor.value.substring(editor.selectionStart, editor.selectionEnd);
  },

  addParagraph: function(align)
  {
    if (align == undefined)
      align = '';
    else
      align = '=' + align;

    this.addTags('[p' + align + ']', '[/p]');
  },

  addBold: function()
  {
    this.addTags('[b]', '[/b]');
  },

  addItalic: function()
  {
    this.addTags('[i]', '[/i]');
  },

  addUnderline: function()
  {
    this.addTags('[u]', '[/u]');
  },
  
  addStrikethrough: function()
  {
    this.addTags('[s]', '[/s]');
  },

  addColor: function(e)
  {
    var colorInput = $('colorLayer' + this.id).down('.normal');

    if (e.target.tagName == 'TD') {
      var color = e.target.getStyle('background-color');
    } else {
      var color = colorInput.getValue();
    }
  
    this.addTags('[color=' + color + ']', '[/color]');
    colorInput.clear();
    this.colorLayer.hide();
  },

  addUrlOld: function()
  {
    this.addTags('[url]', '[/url]', '[url=http://www.example.com]Example site[/url]');
  },

  addUrl: function(e)
  {
    if (!e.target.hasClassName('insertButton')) {
      this.colorLayer.hide();
      var selected = this.selection();
      $('urlLayer' + this.id).down('.urlLink').setValue(selected.startsWith('http://') ? selected : 'http://' + selected);
    } else {
      var title = $('urlLayer' + this.id).down('.urlTitle');
      this.removeSelected();
      if (title.present()) {
        this.add('[url=' + $('urlLayer' + this.id).down('.urlLink').getValue() + ']' + title.getValue() + '[/url]');
      } else {
        this.add('[url]' + $('urlLayer' + this.id).down('.urlLink').getValue() + '[/url]');
      }
      title.clear();
      this.urlLayer.hide();
    }
  },

  addImg: function()
  {
    this.addTags('[img]', '[/img]');
  },

  addHeader: function(level)
  {
    this.addTags('[h' + level + ']', '[/h' + level + ']');
  },

  addEmotion: function(name)
  {
    this.add('[' + name + ']');
  },

  addFile: function(url, filename, mimeType)
  {
    if (filename == undefined && mimeType == undefined)
      this.add('[file]' + filename + '[/file]');
    else if (filename != undefined && mimeType == undefined)
      this.add('[file filename="' + filename + '"]' + url + '[/file]');
    else if (filename == undefined)
      this.add('[file mimetype="' + mimeType + '"]' + url + '[/file]');
    else
      this.add('[file filename="' + filename + '" mimetype="' + mimeType + '"]' + url + '[/file]');
  },
  
  addImage: function(url)
  {
    this.add('[img]' + url + '[/img]');
  },

  registerFileManager: function()
  {
    var thisVar = this;
    var actions = new Array();
    actions[0] = new Object();
    actions[0].name = 'attachButton';
    actions[0].onclick = function () { punistoragemanagerInsertFiles(thisVar); };
    showCustomMessage('fileManagerPopup', actions);
    
    // Setting up the file manager
    var fileContainer = $('popupMessage').down('.fileManager', 1);
    fileContainer.id = 'fileContainer';
    var folderList = $('popupMessage').down('.fileManager').down('tbody');
    folderList.id = 'folderList';
    punistoragemanagerInit();
    punistoragemanagerReloadFilemanager();
    globalErrorOutput = 'inlineErrorMessage';
  },

  toggleEmotions: function()
  {
    var emotions = $('editorEmotions' + this.id);
    if (emotions.visible())
      emotions.hide();
    else
      emotions.show();
  },

  toggleEnabledEmotions: function()
  {
    var smilies = $('editorStatusButtons' + this.id).select('.smiliesButton');
    if (smilies.length == 0)
      smilies = $('editorStatusButtons' + this.id).select('.noSmiliesButton');

    smilies = smilies[0];

    if (smilies.hasClassName('smiliesButton')) {
      smilies.removeClassName('smiliesButton');
      smilies.addClassName('noSmiliesButton');
    } else {
      smilies.addClassName('smiliesButton');
      smilies.removeClassName('noSmiliesButton');
    }
  },

  isEmotionsEnabled: function()
  {
    var smilies = $('editorStatusButtons' + this.id).select('.smiliesButton');
    if (smilies.length == 0)
      smilies = $('editorStatusButtons' + this.id).select('.noSmiliesButton');

    smilies = smilies[0];

    return smilies.hasClassName('smiliesButton');
  },

  showPreview: function(text)
  {
    if (this.previewId == undefined) {
      var area = $('editor' + this.id);
      if (area == undefined)
        return;

      var editor = $('editorArea' + this.id);
      var panel = $('editorPanel' + this.id);

      if (!editor.visible()) {
        $('editorPreview' + this.id).remove();
        $('editorToolbar' + this.id).show();
        editor.show();
        if (panel != undefined)
          panel.show();
      } else {
        var content = new Element('div');
        content.id = 'editorPreview' + this.id;
        content.update(text);
        area.appendChild(content);

        $('editorToolbar' + this.id).hide();
        editor.hide();
        if (panel != undefined)
          panel.hide();
      }
    } else {
      var preview = $(this.previewId);
      preview.show();
      var previewContent = preview.down('#' + this.previewId + 'Content');
      previewContent.update(text);
    }
  },
  
  setSource: function(text)
  {
    $('editorArea' + this.id).setValue(text);
  },

  resizeEditor: function(e)
  {
    var panel = $('editorPanel' + this.id);
    var editor = $('editorArea' + this.id);
    if (editor.disabled)
      return;

    var newHeight = (Event.pointerY(e) - editor.cumulativeOffset().top);

    if (newHeight >= 50) {
      editor.setStyle({ height: newHeight + 'px' });
    }
  },

  moveLeft: function()
  {
    var emotions = this.editor.select('.editorEmotions')[0];
    emotions.scrollLeft -= 10;
    var thisVar = this;
    this.moveTimer = setTimeout(function() {thisVar.moveLeft();}, 30);
  },

  moveRight: function(e)
  {
    var emotions = this.editor.select('.editorEmotions')[0];
    emotions.scrollLeft += 10;
    var thisVar = this;
    this.moveTimer = setTimeout(function() {thisVar.moveRight();}, 30);
  },

  flipLeft: function()
  {
    var emotions = this.editor.select('.editorEmotions')[0];
    emotions.scrollLeft -= emotions.getWidth() + 40;
    clearTimeout(this.moveTimer);
    var thisVar = this;
    this.moveTimer = setTimeout(function() {thisVar.moveLeft();}, 1000);
  },

  flipRight: function()
  {
    var emotions = this.editor.select('.editorEmotions')[0];
    emotions.scrollLeft += emotions.getWidth() - 40;
    clearTimeout(this.moveTimer);
    var thisVar = this;
    this.moveTimer = setTimeout(function() {thisVar.moveRight();}, 1000);
  },

  isVisible: function()
  {
    return $('editorArea' + this.id).visible();
  }
});

function doRegisterEditor(editor, id, disable, embedded)
{
  alert('BUG!');
}

/*
  Code below this point was taken from phpBB code (./styles/prosilver/template/editor.js).
  Thank you for this code.
*/

/**
* From http://www.massless.org/mozedit/
*/
function mozWrap(txtarea, open, close)
{
  var selLength = txtarea.textLength;
  var selStart = txtarea.selectionStart;
  var selEnd = txtarea.selectionEnd;
  var scrollTop = txtarea.scrollTop;

  if (selEnd == 1 || selEnd == 2)
  {
    selEnd = selLength;
  }

  var s1 = (txtarea.value).substring(0,selStart);
  var s2 = (txtarea.value).substring(selStart, selEnd);
  var s3 = (txtarea.value).substring(selEnd, selLength);

  txtarea.value = s1 + open + s2 + close + s3;
  txtarea.selectionStart = selEnd + open.length + close.length;
  txtarea.selectionEnd = txtarea.selectionStart;
  txtarea.focus();
  txtarea.scrollTop = scrollTop;

  return;
}

/**
* Insert at Caret position. Code from
* http://www.faqts.com/knowledge_base/view.phtml/aid/1052/fid/130
*/
function storeCaret(textEl)
{
  if (textEl.createTextRange)
  {
    textEl.caretPos = document.selection.createRange().duplicate();
  }
}

/* Little modified insert function :) */
function insert_text(text, editor)
{
  var textarea = editor;

  if (!isNaN(textarea.selectionStart))
  {
    var sel_start = textarea.selectionStart;
    var sel_end = textarea.selectionEnd;

    mozWrap(textarea, text, '');
    textarea.selectionStart = sel_start + text.length;
    textarea.selectionEnd = sel_end + text.length;
  }
  else if (textarea.createTextRange && textarea.caretPos)
  {
    textarea.focus();
    storeCaret(textarea);

    var caret_pos = textarea.caretPos;
    caret_pos.text = caret_pos.text.charAt(caret_pos.text.length - 1) == ' ' ? caret_pos.text + text + ' ' : caret_pos.text + text;
  }
  else
  {
    textarea.value = textarea.value + text;
  }
}

/**
* Caret Position object
*/
function caretPosition()
{
  var start = null;
  var end = null;
}

function getCaretPosition(txtarea)
{
  var caretPos = new caretPosition();

  // simple Gecko/Opera way
  if(txtarea.selectionStart || txtarea.selectionStart == 0)
  {
    caretPos.start = txtarea.selectionStart;
    caretPos.end = txtarea.selectionEnd;
  }
  // dirty and slow IE way
  else if(document.selection)
  {

    // get current selection
    var range = document.selection.createRange();

    // a new selection of the whole textarea
    var range_all = document.body.createTextRange();
    range_all.moveToElementText(txtarea);

    // calculate selection start point by moving beginning of range_all to beginning of range
    var sel_start;
    for (sel_start = 0; range_all.compareEndPoints('StartToStart', range) < 0; sel_start++)
    {
      range_all.moveStart('character', 1);
    }

    txtarea.sel_start = sel_start;

    // we ignore the end value for IE, this is already dirty enough and we don't need it
    caretPos.start = txtarea.sel_start;
    caretPos.end = txtarea.sel_start;
  }

  return caretPos;
}
