function Editor() {
  var self = this;
  var textarea = null;
  var previewTimer = null;
  var smileys = [{code: ':angry:', image: 'angry'}, {code: ':D(?!rool:)', image: 'biggrin'}, {code: ':blink:', image: 'blink'}, {code: ':blush:', image: 'blushing'}, {code: ':bored:', image: 'bored'}, {code: ':\\?\\?\\?:', image: 'confused'},
                 {code: '8\\)', image: 'cool'}, {code: ':cry:', image: 'crying'}, {code: ':curse:', image: 'cursing'}, {code: ':drool:', image: 'drool'}, {code: ':glare:', image: 'glare'}, {code: ':huh:', image: 'huh'},
                 {code: ':lol:', image: 'laugh'}, {code: ':rofl:', image: 'lol'}, {code: ':x', image: 'mad'}, {code: ':mellow:', image: 'mellow'}, {code: ':ohmy:', image: 'ohmy'}, {code: ':roll:', image: 'rolleyes'},
                 {code: ':\\(', image: 'sad'}, {code: ':scared:', image: 'scared'}, {code: ':sleepy:', image: 'sleep'}, {code: ':\\)', image: 'smile'}, {code: ':sneaky:', image: 'sneaky'}, {code: ':thumbsdown:', image: 'thumbdown'},
                 {code: ':thumbsup:', image: 'thumbup'}, {code: ':love:', image: 'hearts'}, {code: ':P', image: 'raspberry'}, {code: ':unsure:', image: 'unsure'}, {code: ':w00t:', image: 'w00t'}, {code: ';\\)', image: 'wink'}];
  
  function getSelectionExtent() {
    if (document.selection) {
      this.textarea.focus();
      var r = document.selection.createRange();
      return [r.start, r.end];
    }
    else if (typeof textarea.selectionStart != 'undefined') {
      return [textarea.selectionStart, textarea.selectionEnd];
    }
    else {
      return 0;
    }
  }
  
  function getSelectedText() {
    textarea.focus();
    if (typeof textarea.selectionStart != 'undefined') {
      return textarea.value.substr(textarea.selectionStart, textarea.selectionEnd - textarea.selectionStart);
    }
    else if (document.selection && document.selection.createRange) {
      return document.selection.createRange().text;
    }
    else if (window.getSelection) {
      return window.getSelection() + '';
    }
    else {
      return '';
    }
  }

  this.apply = function(cmd, option) {
    switch (cmd) {
      case "bold": applycmd("b"); break; 
      case "underline": applycmd("u"); break; 
      case "strike":  applycmd("s"); break; 
      case "italic":  applycmd("i"); break; 
      case "left":  applycmd("left"); break; 
      case "centre":  applycmd("centre"); break; 
      case "right":  applycmd("right"); break; 
      case "indent":  applycmd("indent"); break; 
      case "quote":  applycmd("quote"); break; 
      case "colour":  applycmd("colour", option); break; 
      case "size":  applycmd("size", option); break; 
      case "unindent":  removetags("indent"); break; 
      case "link":  addlink(); break; 
      case "unlink":  removetags("link"); break; 
      case "image":  addimage(); break; 
      case "smiley":  applysmiley(option); break; 
      case "ul":  makelist("ul"); break; 
      case "ol":  makelist("ol"); break; 
      default: break;
    }
  };
  
  function makelist(type) {
    var items = "";
    var item = null;
    while (item = window.prompt("Enter a list item. Press cancel, or leave the text box empty, to finish the list")) {
      items += "[item]" + item + "[/item]\r\n";
    }
    
    if (items !== "") {
      insertlist(type, items);
    }
  }

  function insertlist(type, items) {
    var list = (type == "ol")?"[ol]" + items + "[/ol]":"[ul]" + items + "[/ul]";
    
    if (typeof textarea.selectionStart != 'undefined') {
      textarea.selectionStart = textarea.selectionEnd;
      textarea.value = textarea.value.substr(0, textarea.selectionStart) + list + textarea.value.substr(textarea.selectionEnd);
    }
    else if (document.selection && document.selection.createRange) {
    }
    else {
      textarea.value += list;
    }
      
    self.startpreview();
  }
  
  function addlink() {
    var url = window.prompt("Enter the url of the link", "http://");
    if (url && (url !== "")) {
      applycmd("link", url);
    }
  }
  
  function addimage() {
    var url = window.prompt("Enter the url of the image", "http://");
    if (url && (url !== "")) {
      applycmd("img", url);
    }
  }
  
  function removetags(tag) {
    var re = new RegExp("\\[" + tag + "(\\:[\\s\\S]*)?\\]([\\s\\S]*)\\[\\/" + tag + "\\]", "img");
    var selectedText = getSelectedText();
    var selLength = selectedText.length;
    selectedText = selectedText.replace(re, "$2");
    
    if (typeof textarea.selectionStart != 'undefined')
    {
      var selStart = textarea.selectionStart + selectedText.length;
      textarea.value = textarea.value.substr(0, textarea.selectionStart) + selectedText + textarea.value.substr(textarea.selectionEnd);
      textarea.selectionStart = selStart;
      textarea.selectionEnd = selStart;
    }
    else if (document.selection && document.selection.createRange)
    {
      var selection = document.selection.createRange();
      selection.text = selectedText.replace(/\r?\n/g, '\r\n');
      selection.select();
    }
    else {
      this.textarea.value += selectedText;
    }
      
    this.startpreview();
  }

  function applycmd(tag, option) {
    var selectedText = getSelectedText();
    var selLength = selectedText.length;
    var tags = [(option)?"[" + tag + ":" + option + "]":"[" + tag + "]", "[/" + tag + "]"];
    selectedText = tags[0] + selectedText + tags[1];
    
    if (typeof textarea.selectionStart != 'undefined') {
      var selStart = textarea.selectionStart;
      textarea.value = textarea.value.substr(0, textarea.selectionStart) + selectedText + textarea.value.substr(textarea.selectionEnd);
      textarea.selectionStart = selStart + tags[0].length;
      textarea.selectionEnd = textarea.selectionStart + selLength;
    }
    else if (document.selection && document.selection.createRange) {
      var selection = document.selection.createRange();
      selection.text = selectedText.replace(/\r?\n/g, '\r\n');
      selection.moveStart('character', -selLength - tags[1].length);
      selection.moveEnd('character', -tags[1].length);
      selection.select();
    }
    else {
      textarea.value += selectedText;
    }
      
    self.startpreview();
  }
  
  function applysmiley(tag) {
    var selectedText = getSelectedText();
    var selLength = selectedText.length;
    
    if (typeof textarea.selectionStart != 'undefined') {
      var selStart = textarea.selectionStart;
      textarea.value = textarea.value.substr(0, textarea.selectionEnd) + tag + textarea.value.substr(textarea.selectionEnd);
      textarea.selectionStart = textarea.selectionEnd + tag.length;
      textarea.selectionEnd = textarea.selectionStart;
    }
    else if (document.selection && document.selection.createRange) {
      var selection = document.selection.createRange();
      selection.text = selectedText.replace(/\r?\n/g, '\r\n');
      selection.text = tag;
      selection.select();
    }
    else {
      textarea.value += tag;
    }
      
    self.startpreview();
  }

  this.startpreview = function() {
    if (previewTimer) {
      clearTimeout(previewTimer);
    }
    previewTimer = setTimeout(preview, 200);
  };

  function convertsmiley(source) {
    var re;
    for (var i=0; i<smileys.length; i++) {
      re = new RegExp(smileys[i].code, "i");
      while (source.match(re)) {
        source = source.replace(re, "<img src=\"/images2/forums/smilies/" + smileys[i].image + ".gif\" />");
      }
    }
    
    return source;
  }

  function preview() {
    var source = $j(textarea).val();
    
    var ops = [{exp: /</, replace: "&lt;"},
               {exp: />/, replace: "&gt;"},
               {exp: /\[b\]([\s\S]*?)\[\/b\]/i, replace: "<span class=\"bold\">$1</span>"},
               {exp: /\[u\]([\s\S]*?)\[\/u\]/i, replace: "<span class=\"underline\">$1</span>"},
               {exp: /\[i\]([\s\S]*?)\[\/i\]/i, replace: "<span class=\"italic\">$1</span>"},
               {exp: /\[s\]([\s\S]*?)\[\/s\]/i, replace: "<span class=\"strikethrough\">$1</span>"},
               {exp: /\[left\]([\s\S]*?)\[\/left\]/i, replace: "<div class=\"la\">$1</div>"},
               {exp: /\[centre\]([\s\S]*?)\[\/centre\]/i, replace: "<div class=\"ca\">$1</div>"},
               {exp: /\[right\]([\s\S]*?)\[\/right\]/i, replace: "<div class=\"ra\">$1</div>"},
               {exp: /\[indent\]([\s\S]*?)\[\/indent\]/i, replace: "<div class=\"indent\">$1</div>"},
               {exp: /\[quote\]([\s\S]*?)\[\/quote\]/i, replace: "<fieldset class=\"quote\"><legend>Quote: </legend>$1</fieldset>"},
               {exp: /\[quote:([\s\S]*?)\]([\s\S]*?)\[\/quote\]/i, replace: "<fieldset class=\"quote\"><legend>Quote: $1</legend>$2</fieldset>"},
               {exp: /\[colour:(\w+)\]([\s\S]*?)\[\/colour\]/i, replace: "<span style=\"color: $1;\">$2</span>"},
               {exp: /\[size:(tiny|small|normal|large|xl)\]([\s\S]*?)\[\/size\]/i, replace: "<span class=\"font$1\">$2</span>"},
               {exp: /\[link:([\s\S]*?)\]([\s\S]*?)\[\/link\]/i, replace: "<a href=\"$1\" target=\"_blank\">$2</a>"},
               {exp: /\[(ul|ol)\]([\s\S]*?)\[item\]([\s\S]*?)\[\/item\]([\s\S]*?)\[\/\1\]/i, replace: "[$1]$2<li>$3</li>$4[/$1]"},
               {exp: /\[(ul|ol)\]([\s\S]*?)\[\/\1\]/i, replace: "<$1>$2</$1>"},
               {exp: /\[img:([\s\S]*?)\]([\s\S]*?)\[\/img\]/i, replace: "<img src=\"$1\" alt=\"$2\" title=\"$2\" />"},
               {exp: /\[ul\]([\s\S]*?)\[\/ul\]/i, replace: "<ul>$1</ul>"},
               {exp: /\r?\n/, replace: "<br />"}];
    
    for (var i=0; i<ops.length; i++) {
      while (source.match(ops[i].exp, ops[i].replace)) {
        source = source.replace(ops[i].exp, ops[i].replace);
      }
    }
        
    source = convertsmiley(source);
    $j("#preview").html(source);
  }
  
  function resetDropDowns() {
    $j(".fontsizelist").css("display", "none");
    $j(".colorgrid").css("display", "none");
    $j(".smileylist").css("display", "none");
    $j("#cbsize").css("background-position", "");
    $j("#pickcolour").css("background-position", "");
    $j("#cbsmiley").css("background-position", "");
  }
  
  this.toggleCombo = function(o) {
    if (o.dropdown.css("display") == "block") {
      o.dropdown.css("display", "none");
      o.button.css("background-position", "");
    }
    else {
      resetDropDowns();
      o.dropdown.css("display", "block");
      o.button.css("background-position", "0 -22px");
      document.onclick = function() {
        document.onclick = function() {
          document.onclick = null;
          o.dropdown.css("display", "none");
          o.button.css("background-position", "");
        };
      };
    }
  };
  
  function init() {
    textarea = $j("#txtreply").keyup(function() { self.startpreview(); }).change(function() { self.startpreview(); }).get(0);
  }
  
  init();
}

function Forums() {
  var self = this;
  var canToggle = true;
  var currentelement = null;
  var currentcontent = null;
  var waiting = false;
  
  this.editor = new Editor();
  
  this.toggle = function(o) {
    if (this.canToggle) {
      this.canToggle = false;
      var restore = function() { self.canToggle = true; return false; };
      var jo = $j("#" + o);
      if (jo.length < 1) return restore();
      (jo.css("display") == "block")?jo.slideUp("normal", restore ):jo.slideDown("normal", restore );
    }
    return false;
  }
  
  function setClock() {
    var dateConverter = {
      Months: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
      Days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
      toString: function(d) {
        var result = this.Days[d.getDay()] + " ";
        var date = d.getDate();
        var d2 = date;
        result += date;
        switch (date) {
          case 1: result += "st "; break; 
          case 21: result += "st "; break;
          case 31: result += "st "; break;
          case 2: result += "nd "; break; 
          case 22: result += "nd "; break;
          case 3: result += "rd "; break; 
          case 23: result += "rd "; break; 
          default: result += "th ";
        }
        result += this.Months[d.getMonth()] + " " + d.getFullYear();
        
        var tmp = d.getHours();
        var meridian = ((tmp >= 12) && (tmp < 24))?"pm":"am";
        if (tmp > 12) tmp += -12;
        if (tmp == 0) tmp = 12;
        result += ", " + tmp + ":";
        
        tmp = d.getMinutes();
        if (tmp < 10) tmp = "0" + tmp;
        result += tmp + meridian;
        return result;
      }
      
    }
    $j(".clock").html(dateConverter.toString(new Date()));
  }
  
  this.notify = function(thread, checkbox) {
    var checked = $j(checkbox).attr("checked");
    $j("input.notify").attr("checked", (checked?"checked":""));
    ajaxpost("/ajax/forumnotify", null, [{name: "threadid", value: thread}, {name: "subscribe", value: $j(checkbox).attr("checked")}]);
  }
  
  
  this.quote = function(id, username) {
    if (!username) username = "";
    ajaxpost("/ajax/quote", quoteHandler, [{name: "id", value: id}, {name: "username", value: username}]);
  }
  
  function quoteHandler(o) {
    if (o.xmlhttp.status == 200) {
      $j("#txtreply").html(o.responseText);
      $j("#txtreply").get(0).focus();
      window.location="#reply";
      self.editor.startpreview();
    }
  }
  
  function init() {
    setClock();
    window.setInterval(setClock, 1000);
  }
  
  this.edit = function(id) {
    $j("#frmEdit").get(0).postid.value=id;
    $j("#frmEdit").get(0).submit();
  };
  
  this.reply = function() {
    if ($j('#txtreply').val().trim() != "")
      $j('#frmreply').get(0).submit();
  };
  
  this.rm = function(id) {
    if (confirm("Are you sure you want to permanently delete this post?\nClick 'OK' to delete, or 'Cancel' to do nothing")) {
      $j("#frmDelete").get(0).postid.value = id;
      $j("#frmDelete").get(0).submit();
    }
  };
  
  
  this.pm = function(user, element, thread, postid) {
    if (!waiting) {
      if (currentelement) {
        currentelement.html(currentcontent);
      }
      currentelement = $j("#" + element);
      currentcontent = currentelement.html();
      waiting = true;
      ajaxpost("/ajax/forumspm.php", function(o) { pmrh(o); }, [{name: "userid", value: user}, {name: "threadid", value: thread}]);
      window.location = "#p" + postid;
    }
  };

  function pmrh(o) {
    waiting = false;
    if (o.xmlhttp.status == 200)
      currentelement.html(o.responseText);
  }
  
  function canpm() {
    var txt = $j('#txtPM').get(0);
    if (txt !== "")
    {
      if (txt.value.trim() == "") alert("Please type your message before pressing the 'Send' button");
      return (txt.value.trim() !== "");
    }
    return false;
  }
  
  this.cancelpm = function() {
    currentelement.html(currentcontent);
    currentelement = null;
    currentcontent = null;
  };
  
  this.report = function(element, postid, threadid) {
    if (!waiting) {
      if (currentelement) {
        currentelement.html(currentcontent);
      }
      currentelement = $j("#" + element);
      currentcontent = currentelement.html();
      waiting = true;
      window.location = "#p" + postid;
      ajaxpost("/ajax/forumsreport.php", function(o) { pmrh(o); }, [{name: "postid", value: postid}, {name: "threadid", value: threadid}]);
    }
  };
  
  function canreport() {
    var txt = $j('#txtMSG').get(0);
    if (txt !== "") {
      if (txt.value.trim() == "") alert("Please explain why you are reporting this post");
      return (txt.value.trim() !== "");
    }
    return false;
  }
  
  init();
  
}

var forums = null;
$j(document).ready(function() { forums = new Forums(); } );
