// Code by Daniel Lew
// Version 1.0

// Valid tags that this converter will work with.
var g_aValidTags = [ 'b', 'i', 'u', 'quote', 'list', '*', 'url', 'img', 'color', 'size', 'code' ];

var g_bHasImage;
var g_iNumImages;

doSigCheck = function()
{
    g_bHasImage = false;
    g_iNumImages = 0;

    var eChecker = document.getElementById("checker");
    var oTreeHead = parseBBCode(eChecker.value);
    var sSig = convert(oTreeHead);
    var eResults = document.getElementById("results");
    eResults.innerHTML = sSig;

    if (!g_bHasImage)
    {
        checkSig();
    }
}

/**
 * Parses bbcode text into a tree.
 */
parseBBCode = function(p_sText)
{
    var aChars = p_sText.split('');

    // Lexical analysis - chunk into tokens
    var aTokens = new Array();
    var aStack = new Array();
    while (aChars.length > 0)
    {
        var cChar = aChars.shift();

        if (cChar == '[' || cChar == ']')
        {
            if (aStack.length > 0)
            {
                aTokens.push(aStack.join(''));
                aStack = new Array();
            }
            aTokens.push(cChar);
        }
        else
        {
            aStack.push(cChar);
        }
    }

    // If there's anything left on the stack, push it on.
    if (aStack.length > 0)
    {
        aTokens.push(aStack.join(''));
    }

    // Create a parse tree
    var oHead = { sType: 'head', aChildren: new Array() };
    var oCurrNode = oHead;
    aStack = new Array();
    while (aTokens.length > 0)
    {
        var sCurrToken = aTokens.shift();

        if (sCurrToken == '[' && aTokens.length > 1 && aTokens[1] == ']')
        {
            var sTag = aTokens.shift();
            var bWasTag = false;

            // If this is a closing tag, check the parent.
            if (sTag.charAt(0) == '/')
            {
                var sNakedTag = sTag.substr(1);
                sNakedTag = sNakedTag.toLowerCase();
                // Special case for [*], because it has no closing tag
                if (oCurrNode.sType == sNakedTag || (oCurrNode.sType == '*' && oCurrNode.oParent.sType == 'list'))
                {
                    if (aStack.length > 0)
                    {
                        oCurrNode.aChildren.push(aStack.join(''));
                        aStack = new Array();
                    }

                    // Special case for [*], because it has no closing tag
                    if (oCurrNode.sType == '*' && oCurrNode.oParent.sType == 'list')
                    {
                        oCurrNode = oCurrNode.oParent;
                    }

                    oCurrNode = oCurrNode.oParent;
                    bWasTag = true;
                }
            }
            // Could be an opening tag, maybe start new node
            else
            {
                var sTrueTag = sTag;
                var sVal = '';
                var iEqLoc = sTag.indexOf('=');
                if (iEqLoc > -1)
                {
                    sTrueTag = sTag.substring(0, iEqLoc);
                    sVal = sTag.substr(iEqLoc + 1);
                }

                sTrueTag = sTrueTag.toLowerCase();

                if (isInArray(g_aValidTags, sTrueTag))
                {
                    if (aStack.length > 0)
                    {
                        oCurrNode.aChildren.push(aStack.join(''));
                        aStack = new Array();
                    }

                    var oNewNode = { sType: sTrueTag, aChildren: new Array(), oParent: oCurrNode };

                    if (sVal != '')
                    {
                        oNewNode.sVal = sVal;
                    }

                    // Special case for [*], because it has no closing tag
                    if (sTrueTag == '*' && oCurrNode.sType == '*')
                    {
                        oCurrNode = oCurrNode.oParent;
                        oNewNode.oParent = oCurrNode;
                    }

                    oCurrNode.aChildren.push(oNewNode);
                    oCurrNode = oNewNode;

                    bWasTag = true;
                }
            }

            // If it was a tag, shift off the finishing ']'
            // Otherwise, do proper shifting onto the stack.
            if (bWasTag)
            {
                aTokens.shift();
            }
            else
            {
                aStack.push(sCurrToken);
                aStack.push(sTag);
            }
        }
        else
        {
            aStack.push(sCurrToken);
        }
    }

    // If there's anything left on the stack, push it on the current node.
    if (aStack.length > 0)
    {
        oCurrNode.aChildren.push(aStack.join(''));
    }

    return oHead;
}

/**
 * Convert BBCode to HTML.
 */
convert = function(p_oNode)
{
    // A little base-casing.
    if (typeof(p_oNode) == 'string')
    {
        var ret = p_oNode;
        ret = convertSmilies(ret);
        ret = ret.replace(/\n/g, '<br \>');
        return ret;
    }

    var sb = [];

    // One big handler for each tag.  Messy, but does the job.
    if (p_oNode.sType == 'head')
    {
        sb[sb.length] = '<span class="postbody">';
        for (a in p_oNode.aChildren) { sb[sb.length] = convert(p_oNode.aChildren[a]); }
        sb[sb.length] = '</span>';
    }
    else if (p_oNode.sType == 'b')
    {
        sb[sb.length] = '<span style="font-weight:bold">';
        for (a in p_oNode.aChildren) { sb[sb.length] = convert(p_oNode.aChildren[a]); }
        sb[sb.length] = '</span>';
    }
    else if (p_oNode.sType == 'i')
    {
        sb[sb.length] = '<span style="font-style:italic">';
        for (a in p_oNode.aChildren) { sb[sb.length] = convert(p_oNode.aChildren[a]); }
        sb[sb.length] = '</span>';
    }
    else if (p_oNode.sType == 'u')
    {
        sb[sb.length] = '<span style="text-decoration:underline">';
        for (a in p_oNode.aChildren) { sb[sb.length] = convert(p_oNode.aChildren[a]); }
        sb[sb.length] = '</span>';
    }
    else if (p_oNode.sType == 'quote')
    {
        var sName,
            bFailure = false;
        if (p_oNode.sVal)
        {
            sName = p_oNode.sVal;
            if (sName.length < 2 || sName.charAt(0) != '"' || sName.charAt(sName.length - 1) != '"')
            {
                bFailure = true;
            }
            else
            {
                sName = sName.substring(1, sName.length - 1);

                // phpBB is REALLY fucked up and actually lets you
                // enter whatever the fuck you want in the signature name.
                // Thus, we parse and render the whole fucker just in case.
                var oTmpHead = parseBBCode(sName);
                sName = convert(oTmpHead);
            }
        }

        if (bFailure)
        {
            sb[sb.length] = '[quote=';
            sb[sb.length] = p_oNode.sVal;
            sb[sb.length] = ']';
            for (a in p_oNode.aChildren) { sb[sb.length] = convert(p_oNode.aChildren[a]); }
            sb[sb.length] = '[/quote]';
        }
        else
        {
            sb[sb.length] = '</span><table cellspacing="1" cellpadding="3" border="0" align="center" width="90%"><tbody><tr><td><span class="genmed"><b>';
            if (p_oNode.sVal)
            {
                sb[sb.length] = sName;
                sb[sb.length] = ' wrote:'
            }
            else
            {
                sb[sb.length] = 'Quote:';
            }
            sb[sb.length] = '</b></span></td></tr><tr><td class="quote">';
            for (a in p_oNode.aChildren) { sb[sb.length] = convert(p_oNode.aChildren[a]); }
            sb[sb.length] = '</td></tr></tbody></table><span class="postbody">';
        }
    }
    else if (p_oNode.sType == 'list')
    {
        sb[sb.length] = '<ul>';
        for (a in p_oNode.aChildren) { sb[sb.length] = convert(p_oNode.aChildren[a]); }
        sb[sb.length] = '</ul>';
    }
    else if (p_oNode.sType == '*')
    {
        sb[sb.length] = '<li>';
        for (a in p_oNode.aChildren) { sb[sb.length] = convert(p_oNode.aChildren[a]); }
        sb[sb.length] = '</li>';
    }
    else if (p_oNode.sType == 'url')
    {
        var sLink;
        if (p_oNode.sVal)
        {
            sLink = p_oNode.sVal;
        }
        else
        {
            var tmpSb = [];
            for (a in p_oNode.aChildren) { tmpSb[tmpSb.length] = convert(p_oNode.aChildren[a]); }
            sLink = tmpSb.join('');
        }

        sb[sb.length] = '<a class="postlink" target="_blank" href="';
        sb[sb.length] = sLink;
        sb[sb.length] = '">';
        if (p_oNode.sVal)
        {
            for (a in p_oNode.aChildren) { sb[sb.length] = convert(p_oNode.aChildren[a]); }
        }
        else
        {
            sb[sb.length] = sLink;
        }
        sb[sb.length] = '</a>';
    }
    else if (p_oNode.sType == 'img')
    {
        var tmpSb = [];
        for (a in p_oNode.aChildren) { tmpSb[tmpSb.length] = convert(p_oNode.aChildren[a]); }
        var sLink = tmpSb.join('');
        sb[sb.length] = '<img border="0" src="';
        sb[sb.length] = sLink;
        g_bHasImage = true;
        g_iNumImages++;
        sb[sb.length] = '" onload="loadedImage()';
        sb[sb.length] = '"/>'
    }
    else if (p_oNode.sType == 'color')
    {
        sb[sb.length] = '<span style="color:';
        sb[sb.length] = p_oNode.sVal;
        sb[sb.length] = '">';
        for (a in p_oNode.aChildren) { sb[sb.length] = convert(p_oNode.aChildren[a]); }
        sb[sb.length] = '</span>';
    }
    else if (p_oNode.sType == 'size')
    {
        var nSize = parseInt(p_oNode.sVal);
        var bFailure = (nSize < 1 || nSize > 29);

        if (bFailure)
        {
            sb[sb.length] = '[size=';
            sb[sb.length] = p_oNode.sVal;
            sb[sb.length] = ']';
            for (a in p_oNode.aChildren) { sb[sb.length] = convert(p_oNode.aChildren[a]); }
            sb[sb.length] = '[/size]';
        }
        else
        {
            sb[sb.length] = '<span style="font-size: ';
            sb[sb.length] = nSize;
            sb[sb.length] = 'px; line-height: normal;">';
            for (a in p_oNode.aChildren) { sb[sb.length] = convert(p_oNode.aChildren[a]); }
            sb[sb.length] = '</span>';
        }
    }
    else if (p_oNode.sType == 'code')
    {
        sb[sb.length] = '</span><table cellspacing="1" cellpadding="3" border="0" align="center" width="90%"><tbody><tr><td><span class="genmed"><b>Code:</b></span></td></tr><tr><td class="code">';
        for (a in p_oNode.aChildren) { sb[sb.length] = convertCode(p_oNode.aChildren[a]); }
        sb[sb.length] = '</td></tr></tbody></table><span class="postbody">';
    }

    return sb.join('');
}

/**
 * Special case for [code] tags, regenerates the
 * original bbcode.
 */
convertCode = function(p_oNode)
{
    // A little base-casing.
    if (typeof(p_oNode) == 'string')
    {
        return escapeHTML(p_oNode);
    }

    var sb = [];

    // Opening tag
    sb[sb.length] = '[';
    sb[sb.length] = p_oNode.sType;
    if (p_oNode.sVal)
    {
        sb[sb.length] = '=';
        sb[sb.length] = p_oNode.sVal;
    }
    sb[sb.length] = ']';

    for (a in p_oNode.aChildren) { sb[sb.length] = convertCode(p_oNode.aChildren[a]); }

    // Closing tag
    sb[sb.length] = '[/';
    sb[sb.length] = p_oNode.sType;
    sb[sb.length] = ']';

    return sb.join('');
}

/**
 * Utility function.
 */
isInArray = function(p_aArray, p_sItem)
{
    for (var a = 0; a < p_aArray.length; a++)
    {
        if (p_aArray[a] == p_sItem)
        {
            return true;
        }
    }

    return false;
}

/**
 * Converts text to have smileys.
 */
convertSmilies = function(p_sText)
{
    var sText = p_sText;

    if (p_sText.length > 2)
    {
        // Yes, this is slow and ugly, but it is easy to write,
        // maintain, and this thing does not need to run super fast.

        var sSmileyRoot = 'http://www.scorehero.com/forum/images/smiles/';
        sText = sText.replace(/:blank:/g, '<img src="' + sSmileyRoot + 'aiwebs_000.gif" border="0" />');
        sText = sText.replace(/:-\//g, '<img src="' + sSmileyRoot + 'aiwebs_001.gif" border="0" />');
        sText = sText.replace(/:-\|/g, '<img src="' + sSmileyRoot + 'aiwebs_002.gif" border="0" />');
        sText = sText.replace(/\^\.\^/g, '<img src="' + sSmileyRoot + 'aiwebs_004.gif" border="0" />');
        sText = sText.replace(/x\.x/g, '<img src="' + sSmileyRoot + 'aiwebs_007.gif" border="0" />');
        sText = sText.replace(/:D/g, '<img src="' + sSmileyRoot + 'aiwebs_011.gif" border="0" />');
        sText = sText.replace(/:drool:/g, '<img src="' + sSmileyRoot + 'aiwebs_012.gif" border="0" />');
        sText = sText.replace(/:tooth:/g, '<img src="' + sSmileyRoot + 'aiwebs_017.gif" border="0" />');
        sText = sText.replace(/:resent:/g, '<img src="' + sSmileyRoot + 'aiwebs_018.gif" border="0" />');
        sText = sText.replace(/e\.e/g, '<img src="' + sSmileyRoot + 'aiwebs_022.gif" border="0" />');
        sText = sText.replace(/@\.@/g, '<img src="' + sSmileyRoot + 'aiwebs_023.gif" border="0" />');
        sText = sText.replace(/:-\\/g, '<img src="' + sSmileyRoot + 'aiwebs_006.gif" border="0" />');
        sText = sText.replace(/o\.\.o/g, '<img src="' + sSmileyRoot + 'aiwebs_010.gif" border="0" />');
        sText = sText.replace(/Oo\//g, '<img src="' + sSmileyRoot + 'aiwebs_014.gif" border="0" />');
        sText = sText.replace(/:\\\//g, '<img src="' + sSmileyRoot + 'aiwebs_015.gif" border="0" />');
        sText = sText.replace(/OoO/g, '<img src="' + sSmileyRoot + 'aiwebs_016.gif" border="0" />');
        sText = sText.replace(/0\.0-/g, '<img src="' + sSmileyRoot + 'aiwebs_019.gif" border="0" />');
        sText = sText.replace(/-ovo-/g, '<img src="' + sSmileyRoot + 'aiwebs_020.gif" border="0" />');
        sText = sText.replace(/O\.\\/g, '<img src="' + sSmileyRoot + 'aiwebs_021.gif" border="0" />');
        sText = sText.replace(/#\.#/g, '<img src="' + sSmileyRoot + 'aiwebs_024.gif" border="0" />');
        sText = sText.replace(/o-\)/g, '<img src="' + sSmileyRoot + 'aiwebs_025.gif" border="0" />');
        sText = sText.replace(/-o-o\)/g, '<img src="' + sSmileyRoot + 'aiwebs_026.gif" border="0" />');
        sText = sText.replace(/--\.-/g, '<img src="' + sSmileyRoot + 'aiwebs_027.gif" border="0" />');
        sText = sText.replace(/o\.o\|/g, '<img src="' + sSmileyRoot + 'aiwebs_029.gif" border="0" />');
        sText = sText.replace(/<>\.\|/g, '<img src="' + sSmileyRoot + 'aiwebs_030.gif" border="0" />');
        sText = sText.replace(/oo<\|/g, '<img src="' + sSmileyRoot + 'aiwebs_031.gif" border="0" />');
        sText = sText.replace(/oo\//g, '<img src="' + sSmileyRoot + 'aiwebs_032.gif" border="0" />');
        sText = sText.replace(/o\.o/g, '<img src="' + sSmileyRoot + 'aiwebs_005.gif" border="0" />');
        sText = sText.replace(/-o-o/g, '<img src="' + sSmileyRoot + 'aiwebs_013.gif" border="0" />');
        sText = sText.replace(/>:\)/g, '<img src="' + sSmileyRoot + 'aiwebs_028.gif" border="0" />');
        sText = sText.replace(/:\)/g, '<img src="' + sSmileyRoot + 'aiwebs_008.gif" border="0" />');
        sText = sText.replace(/:\(/g, '<img src="' + sSmileyRoot + 'aiwebs_003.gif" border="0" />');
        sText = sText.replace(/:mrgreen:/g, '<img src="' + sSmileyRoot + 'icon_mrgreen.gif" border="0" />');
        sText = sText.replace(/\(\*\*\*\)/g, '<img src="' + sSmileyRoot + 'rating_3.gif" border="0" />');
        sText = sText.replace(/\(\*\*\*\*\)/g, '<img src="' + sSmileyRoot + 'rating_4.gif" border="0" />');
        sText = sText.replace(/\(\*\*\*\*\*\)/g, '<img src="' + sSmileyRoot + 'rating_5.gif" border="0" />');
        sText = sText.replace(/:G:/g, '<img src="' + sSmileyRoot + 'fret-g.gif" border="0" />');
        sText = sText.replace(/:R:/g, '<img src="' + sSmileyRoot + 'fret-r.gif" border="0" />');
        sText = sText.replace(/:Y:/g, '<img src="' + sSmileyRoot + 'fret-y.gif" border="0" />');
        sText = sText.replace(/:B:/g, '<img src="' + sSmileyRoot + 'fret-b.gif" border="0" />');
        sText = sText.replace(/:O:/g, '<img src="' + sSmileyRoot + 'fret-o.gif" border="0" />');
        sText = sText.replace(/:GR:/g, '<img src="' + sSmileyRoot + 'fret-gr.gif" border="0" />');
        sText = sText.replace(/:GY:/g, '<img src="' + sSmileyRoot + 'fret-gy.gif" border="0" />');
        sText = sText.replace(/:GB:/g, '<img src="' + sSmileyRoot + 'fret-gb.gif" border="0" />');
        sText = sText.replace(/:GO:/g, '<img src="' + sSmileyRoot + 'fret-go.gif" border="0" />');
        sText = sText.replace(/:RY:/g, '<img src="' + sSmileyRoot + 'fret-ry.gif" border="0" />');
        sText = sText.replace(/:RB:/g, '<img src="' + sSmileyRoot + 'fret-rb.gif" border="0" />');
        sText = sText.replace(/:RO:/g, '<img src="' + sSmileyRoot + 'fret-ro.gif" border="0" />');
        sText = sText.replace(/:YB:/g, '<img src="' + sSmileyRoot + 'fret-yb.gif" border="0" />');
        sText = sText.replace(/:YO:/g, '<img src="' + sSmileyRoot + 'fret-yo.gif" border="0" />');
        sText = sText.replace(/:BO:/g, '<img src="' + sSmileyRoot + 'fret-bo.gif" border="0" />');
        sText = sText.replace(/:GRY:/g, '<img src="' + sSmileyRoot + 'fret-gry.gif" border="0" />');
        sText = sText.replace(/:GRB:/g, '<img src="' + sSmileyRoot + 'fret-grb.gif" border="0" />');
        sText = sText.replace(/:GYB:/g, '<img src="' + sSmileyRoot + 'fret-gyb.gif" border="0" />');
        sText = sText.replace(/:RYB:/g, '<img src="' + sSmileyRoot + 'fret-ryb.gif" border="0" />');
        sText = sText.replace(/:RYO:/g, '<img src="' + sSmileyRoot + 'fret-ryo.gif" border="0" />');
        sText = sText.replace(/:RBO:/g, '<img src="' + sSmileyRoot + 'fret-rbo.gif" border="0" />');
        sText = sText.replace(/:YBO:/g, '<img src="' + sSmileyRoot + 'fret-ybo.gif" border="0" />');
        sText = sText.replace(/:-:/g, '<img src="' + sSmileyRoot + 'fret-blank.gif" border="0" />');
        sText = sText.replace(/:GYO:/g, '<img src="' + sSmileyRoot + 'fret-gyo.gif" border="0" />');
        sText = sText.replace(/:GBO:/g, '<img src="' + sSmileyRoot + 'fret-gbo.gif" border="0" />');
        sText = sText.replace(/:GRO:/g, '<img src="' + sSmileyRoot + 'fret-gro.gif" border="0" />');
    }

    return sText;
}

// Some constants for rules that signatures must abide by.
var MAX_HEIGHT = 170;
var MAX_WIDTH = 800;

loadedImage = function()
{
    g_iNumImages--;
    if (g_iNumImages == 0)
    {
        checkSig();
    }
}

checkSig = function()
{
    var eSig = document.getElementById("results");
    var eAnalysis = document.getElementById("analysis");
    var eSigLimits = document.getElementById("siglimits");

    var aSigImages = eSig.getElementsByTagName('img');
    var iStatImgHeight = 0;
    for (var b = 0; b < aSigImages.length; b++)
    {
        if (aSigImages[b].src.indexOf("http://www.scorehero.com/images/userstats/") >= 0
            && aSigImages[b].offsetHeight > iStatImgHeight)
        {
            iStatImgHeight = aSigImages[b].offsetHeight;
        }
    }

    var iAllowedHeight = MAX_HEIGHT + iStatImgHeight;
    eSigLimits.style.height = iAllowedHeight + 'px';
    eSig.style.width = MAX_WIDTH + 'px';
    eSigLimits.style.width = MAX_WIDTH + 'px';
}

/**
 * Grabbed from http://groups.google.co.nz/group/comp.lang.javascript/browse_thread/thread/e5a0680bb1602a29/8c03ac60ada4740d?lnk=raot
 */
function escapeHTML(s)
{
return s.replace(
  /[&<>"]/g,
  function(m)
  {
    var map = {
      "&": "amp",
      "<": "lt",
      ">": "gt",
      '"': "quot"
    };

    return "&" + map[m] + ";";
  });
}

displayHide = function(p_sId)
{
    var el = document.getElementById(p_sId);
    el.style.display = (el.style.display == 'none') ? '' : 'none';
}
