// Cross Browser selectionStart/selectionEnd
// Version 0.2
// Copyright (c) 2005-2007 KOSEKI Kengo
// 
// This script is distributed under the MIT licence.
// http://www.opensource.org/licenses/mit-license.php
function Selection(textareaElement) {
    this.element = textareaElement;
}

Selection.prototype.getSelection = function() {
    if (document.selection != null && this.element.selectionStart == null) {
        return this._ieGetSelection();
    } else {
        return this._mozillaGetSelection();
    }
};

Selection.prototype._mozillaGetSelection = function() {
    return { 
        start: this.element.selectionStart, 
        end: this.element.selectionEnd 
    };
};

Selection.prototype._ieGetSelection = function() {
    this.element.focus();

    var range = document.selection.createRange();
    var bookmark = range.getBookmark();

    var contents = this.element.value;
    var originalContents = contents;
    var marker = this._createSelectionMarker();
    while(contents.indexOf(marker) != -1) {
        marker = this._createSelectionMarker();
    }

    var parent = range.parentElement();
    if (parent == null || parent.type != "textarea") {
        return { start: 0, end: 0 };
    }
    range.text = marker + range.text + marker;
    contents = this.element.value;

    var result = {};
    result.start = contents.indexOf(marker);
    contents = contents.replace(marker, "");
    result.end = contents.indexOf(marker);

    this.element.value = originalContents;
    range.moveToBookmark(bookmark);
    range.select();

    return result;
};

Selection.prototype._createSelectionMarker = function() {
    return "##SELECTION_MARKER_" + Math.random() + "##";
};


/**
 * Dreamlevels part
 *   - selection updates
 *   - bb codes functionality
 */
$b = jQuery.noConflict();

Selection.prototype.setPosition = function (start, end) 
{
  if (this.element.selectionStart == null)
  {
    var range = this.element.createTextRange();
    var m_s = this.element.value.substring(0, start).match(/\r/g);
    var m_e = this.element.value.substring(start, end).match(/\r/g);
	m_s = (m_s != null ? m_s.length : 0);
	m_e = (m_e != null ? m_e.length : 0);
    
    if (start == end)
    {
      range.move('character', start - m_s);
    }
    else
    {    	
      range.collapse(true);    	
      range.moveStart('character', start - m_s);
      range.moveEnd('character', end - start - m_e);
    }
    range.select();    
  }
  else
  {
    this.element.setSelectionRange(start, end);
  }
};


$b.fn.bbeditor = function(options)
{
  var textarea = this;
  var id = textarea.attr('id');
  var previewID = id + '_preview';
  var previewText = options.previewText ? options.previewText : 'Preview'; 
  textarea.bind('click keyup',  function(e) {previewBB(id);});
  
  controls = $b('<div></div>').addClass('bb-controls').insertBefore(textarea);
  $b('<div></div>').addClass('bb-preview').attr('id', previewID).insertAfter(textarea);
  $b('<div></div>').addClass('bb-preview-title').html(previewText).insertAfter(textarea);
  if (options.buttonText)
  {
    if (options.b) $b('<input type="button" title="bold" />').addClass('bb-b').val(options.b).click(function() {insertBB(id, 'b');}).appendTo(controls);
    if (options.i) $b('<input type="button" title="italic" />').addClass('bb-i').val(options.i).click(function() {insertBB(id, 'i');}).appendTo(controls);
    if (options.u) $b('<input type="button" title="underline" />').addClass('bb-u').val(options.u).click(function() {insertBB(id, 'u');}).appendTo(controls);
    if (options.s) $b('<input type="button" title="size" />').addClass('bb-s').val(options.s).click(function() {insertBB(id, 's');}).appendTo(controls);
    if (options.c) $b('<input type="button" title="color" />').addClass('bb-c').val(options.c).click(function() {insertBB(id, 'c');}).appendTo(controls);
    if (options.m) $b('<input type="button" title="insert &quot;more&quot; tag" />').addClass('bb-m').val(options.m).click(function() {insertBB(id, 'm');}).appendTo(controls);
    if (options.undo) $b('<input type="button" title="undo" />').addClass('bb-undo').val(options.undo).click(function() {undoBB(id);}).appendTo(controls);
  }
  else
  {
    if (options.b) $b('<input type="button" title="bold" />').addClass('bb-b').click(function() {insertBB(id, 'b');}).appendTo(controls);
    if (options.i) $b('<input type="button" title="italic" />').addClass('bb-i').click(function() {insertBB(id, 'i');}).appendTo(controls);
    if (options.u) $b('<input type="button" title="underline" />').addClass('bb-u').click(function() {insertBB(id, 'u');}).appendTo(controls);
    if (options.s) $b('<input type="button" title="size" />').addClass('bb-s').click(function() {insertBB(id, 's');}).appendTo(controls);
    if (options.c) $b('<input type="button" title="color" />').addClass('bb-c').click(function() {insertBB(id, 'c');}).appendTo(controls);
    if (options.m) $b('<input type="button" title="insert &quot;more&quot; tag" />').addClass('bb-m').click(function() {insertBB(id, 'm');}).appendTo(controls);
    if (options.undo) $b('<input type="button" title="undo" />').addClass('bb-undo').click(function() {undoBB(id);}).appendTo(controls);
  }
};

var BBCache = new Array();
function undoBB(id, nopreview)
{
  if (BBCache[id] != null && BBCache[id].length > 0)
  {
	document.getElementById(id).value = BBCache[id].pop();
    if (!nopreview) previewBB(id);
  }
}

function parseBB(txt)
{
  var _search = [
	/\[b\](.*?)\[\/b\]/gi,
	/\[u\](.*?)\[\/u\]/gi,
	/\[i\](.*?)\[\/i\]/gi,
	/\[size=(.*?)\](.*?)\[\/size\]/gi,
	/\[color=(.*?)\](.*?)\[\/color\]/gi];
  
  var _replace = [
	'<span style="font-weight: bold;">$1<\/span>',
	'<span style="text-decoration: underline;">$1<\/span>',
	'<span style="font-style: italic;">$1<\/span>',
	'<span style="font-size: $1;">$2<\/span>',
	'<span style="color: $1;">$2<\/span>'];

  txt = txt.replace('/</g','&lt;');
  txt = txt.replace('/>/g','&gt;');
  txt = txt.replace(/[\r\n]/g, '<br />');
  for(var i in _search)
  {
	txt = txt.replace(_search[i], _replace[i]);
  }
  return txt;
}

function previewBB(id)
{
  var obj1 = document.getElementById(id);
  var obj2 = document.getElementById(id + '_preview');
  if (obj1 && obj2)
  {
    obj2.innerHTML = parseBB(obj1.value);
  }
}

function insertBB(id, bbcode, nopreview)
{
  try
  {
	var obj = document.getElementById(id);

    if (BBCache[id] == null)
    {
    	BBCache[id] = new Array();
    }
    BBCache[id].push(obj.value);

    obj.focus();
    var selection = new Selection(obj);
    var s = selection.getSelection();
    var startPos = s.start;
    var endPos = s.end;
    var s1 = obj.value.substring(0, s.start);
    var s2 = obj.value.substring(s.start, s.end);
    var s3 = obj.value.substring(s.end);

    if (bbcode == 'b' || bbcode == 'u' || bbcode == 'i')
    {
      re1 = new RegExp('\\[' + bbcode + '\\]$');
      re2 = new RegExp('^\\[/' + bbcode + '\\]');
      
      if (re1.test(s1) && re2.test(s3))
	  {
    	s1 = s1.replace(re1, '');
    	s3 = s3.replace(re2, '');
        obj.value = s1 + s2 + s3;
        selection.setPosition(startPos - 3, endPos - 3);
	  }
      else
      {
    	obj.value = s1 + '[' + bbcode + ']' + s2 + '[/' + bbcode + ']' + s3;
        selection.setPosition(startPos + 3, endPos + 3);
      }
    }
    else if (bbcode == 's')
    {
      obj.value = s1 + '[size=%]' + s2 + '[/size]' + s3;
      selection.setPosition(startPos + 6, startPos + 6);
    }
    else if (bbcode == 'c')
    {
      obj.value = s1 + '[color=#]' + s2 + '[/color]' + s3;
      selection.setPosition(startPos + 8, startPos + 8);
    }
    else if (bbcode == 'm')
    {
      obj.value = s1 + '<!-- more -->' + s2 + s3;
      selection.setPosition(startPos + 13, startPos + 13);      
    }
    if (!nopreview) previewBB(id);
  }
  catch (ex)
  {
    1;
  }
}

