var wordIndex       = null;
var wordList        = null;
var foList          = null;
var cwList          = null;
var pList           = null;
var allWordCount    = 0;
var disinctWords    = 0;
var adverbCount     = 0;
var foCount         = 0;
var msText          = "";

function showStatus( sText )
{
    document.getElementById( 'status' ).innerHTML = "<span style='color:maroon'>" + sText + "</span>";
}

function startAction()
{
    showStatus( 'Analyzing... please wait... (this may take a few minutes)' );
    clearDisplay();            
    
    window.setTimeout( 'analyze()', 100 );
}

function analyze()
{
    try
    {
        msText          = removeFormatting( document.getElementById( 'msText' ).value );
        var allWords    = msText.split( ' ' );
        wordIndex       = { };
        wordList        = new Array();
        allWordCount    = allWords.length;
        adverbCount     = 0;
        foCount         = 0;
        
        readLists();
        
        var wordText;
        var wordTextToUse;
        var curWord;
        var curWordList;
        var isFo;
        var isCommon;
        for ( var i = 0; i < allWords.length; i++ )
        {
            wordText        = allWords[i].toString();
            wordTextToUse   = wordText;
            isFo            = ( foList[wordText] ? true : false );
            isCommon        = ( cwList[wordText] ? true : false );
            
            if ( isFo )
                wordTextToUse = foList[wordText].word;
            else if ( isCommon )
                wordTextToUse = cwList[wordText].word;  
            
            if ( wordTextToUse == undefined )
                wordTextToUse = wordText;
            
            curWord = wordIndex[wordTextToUse];
            
            if ( curWord == null || curWord == undefined )
            {
                curWord = new wordData( wordTextToUse, 'Word', isFo, isCommon );
                wordIndex[wordTextToUse] = curWord
                wordList.push( curWord );
            }

            if ( curWord.isAdverb )
                adverbCount++;
            if ( curWord.isFO )
                foCount++;
            
            curWord.count++;
        }
        
        disinctWords    = wordList.length;
        foCount         += findPhrases();

        showStatus( 'Analysis complete! (' + 
            addCommas( allWordCount ) + ' total words, ' +
            addCommas( disinctWords ) + ' distinct words, ' + 
            addCommas( adverbCount ) + ' possible adverbs, ' +
            addCommas( foCount ) + ' frequent offenders)' );
        displayList(false);
    }
    catch (e )
    {
        alert( e );
    }
}

function findPhrases()
{
    var total       = 0;
    var occurrences = 0;
    var curWord;
    var fullPhrase;
    for ( phrase in pList )
    {
        occurrences = findNumberOfOccurrences( msText, phrase );

        if ( occurrences == 0 )
            continue;

        total += occurrences;
        fullPhrase = pList[phrase].word;
        curWord = wordIndex[fullPhrase];
            
        if ( curWord == null || curWord == undefined )
        {
            curWord = new wordData( fullPhrase, 'Phrase', true, false );
            wordIndex[fullPhrase] = curWord
            wordList.push( curWord );
        }
        curWord.count += occurrences;
    }

    return total;
}

function findNumberOfOccurrences( source, target )
{
    if ( target == '' )
        return 0;

    var found       = 0;
    var totFinds    = 0;
    
    for ( var i = 0; i < source.length; i++ )
    {
        found = source.indexOf( target, i );

        if ( found > 0 )
        {
            totFinds++;
            i = found;
        }
        else
            break;
    }

    return totFinds;
}

function wordData( word, wordType, isFo, isCommon )
{
    try
    {
        this.word       = word;
        this.count      = 0;
        this.isAdverb   = endsWithLy( word );
        this.wordType   = wordType;
        this.isFO       = isFo;
        this.isCommon   = isCommon;
        
        if ( word.indexOf( '/' ) <= 0 )
            this.wordLength = word.length;
        else
            this.wordLength = word.indexOf( '/' );
            
        this.isLarge   = ( this.wordLength > 5 );
    }
    catch ( e )
    {
        alert( "word:|" + word + "|\n" + e );
    }
}

function wordListData( word )
{
    this.word       = word;
    this.wordList   = word.split( '/' );
}

function clearDisplay()
{
    document.getElementById( 'words' ).removeChild( document.getElementById( 'words' ).childNodes[0] );
    document.getElementById( 'counts' ).removeChild( document.getElementById( 'counts' ).childNodes[0] );
    document.getElementById( 'totalpercent' ).removeChild( document.getElementById( 'totalpercent' ).childNodes[0] );
    document.getElementById( 'fo' ).removeChild( document.getElementById( 'fo' ).childNodes[0] );
    document.getElementById( 'common' ).removeChild( document.getElementById( 'common' ).childNodes[0] );
    document.getElementById( 'adverb' ).removeChild( document.getElementById( 'adverb' ).childNodes[0] );
    document.getElementById( 'wordtype' ).removeChild( document.getElementById( 'wordtype' ).childNodes[0] );
    document.getElementById( 'large' ).removeChild( document.getElementById( 'large' ).childNodes[0] );
    document.getElementById( 'characters' ).removeChild( document.getElementById( 'characters' ).childNodes[0] );
    
    document.getElementById( 'words' ).innerHTML = "---";
    document.getElementById( 'counts' ).innerHTML = "---";
    document.getElementById( 'totalpercent' ).innerHTML = "---";
    document.getElementById( 'fo' ).innerHTML = "---";
    document.getElementById( 'common' ).innerHTML = "---";
    document.getElementById( 'adverb' ).innerHTML = "---";
    document.getElementById( 'wordtype' ).innerHTML = "---";
    document.getElementById( 'large' ).innerHTML = "---";
    document.getElementById( 'characters' ).innerHTML = "---";
}

function displayList( isForSort )
{
    if ( isForSort )
        clearDisplay();
        
    var sortFunction    = eval( document.getElementById( 'cboSort' ).value );
    var comAct          = document.getElementById( 'cboCommon' ).value;
    var countLimit      = Number( document.getElementById( 'cboCount' ).value );
    var filterType      = Number( document.getElementById( 'cboFilter' ).value );
    var filterText      = document.getElementById( 'txtFilter' ).value;
    var regEndsWith     = new RegExp( filterText + "$");
    
    if ( wordList == null )
        return;
        
    wordList.sort( sortFunction );
    
    var wordText = new StringBuffer();
    var countText = new StringBuffer();
    var totalPercentText = new StringBuffer();
    var foText = new StringBuffer();
    var commonText = new StringBuffer();
    var adverbText = new StringBuffer();
    var wordTypeText = new StringBuffer();
    var largeText = new StringBuffer();
    var charactersText = new StringBuffer();
    for ( var i = 0; i < wordList.length; i++ )
    {
        switch ( comAct )
        {
            case "fo":
                if ( wordList[i].isCommon && !wordList[i].isFO )
                    continue;
                break;
            case "none":
                if ( wordList[i].isCommon )
                    continue;
                break;
        }
        
        if ( wordList[i].count <= countLimit && !wordList[i].isFO )
            continue;
            
        if ( filterText != "" )
        {
            switch ( filterType )
            {
                case 0: //Contains
                    if ( wordList[i].word.indexOf( filterText ) < 0 )
                        continue;
                    break;
                case 1: //Equals
                    if ( wordList[i].word != filterText )
                        continue;
                    break;
                case 2: //Starts With
                    if ( wordList[i].word.indexOf( filterText ) != 0 )
                        continue;
                    break;
                case 3: //Ends With
                    
                    if ( !regEndsWith.test( wordList[i].word ) )
                        continue;
                    break;
            }
        }
        
        if ( wordList[i].word.length > 25 )
            wordText.append( wordList[i].word.substring( 0, 25 ) + "...<br>" );
        else
            wordText.append( wordList[i].word + "<br>" );
        countText.append( wordList[i].count + "<br>" );
        totalPercentText.append( ( wordList[i].count / allWordCount ).toFixed(6) + "<br>" );
        foText.append( ( wordList[i].isFO ? "FO" : "" ) + "<br>" );
        commonText.append( ( wordList[i].isCommon ? "COM" : "" ) + "<br>" );
        adverbText.append( ( wordList[i].isAdverb ? "ADV" : "" ) + "<br>" );
        wordTypeText.append( wordList[i].wordType + "<br>" );
        largeText.append( ( wordList[i].isLarge ? "LRG" : "" ) + "<br>" );
        charactersText.append( wordList[i].wordLength + "<br>" );
    }
    
    //may want to use createTextNode at some point
    document.getElementById( 'words' ).innerHTML = "<span>" + wordText.toString() + "</span>";
    document.getElementById( 'counts' ).innerHTML = "<span>" + countText.toString() + "</span>";
    document.getElementById( 'totalpercent' ).innerHTML = "<span>" + totalPercentText.toString() + "</span>";
    document.getElementById( 'fo' ).innerHTML = "<span>" + foText.toString() + "</span>";
    document.getElementById( 'common' ).innerHTML = "<span>" + commonText.toString() + "</span>";
    document.getElementById( 'adverb' ).innerHTML = "<span>" + adverbText.toString() + "</span>";
    document.getElementById( 'wordtype' ).innerHTML = "<span>" + wordTypeText.toString() + "</span>";
    document.getElementById( 'large' ).innerHTML = "<span>" + largeText.toString() + "</span>";
    document.getElementById( 'characters' ).innerHTML = "<span>" + charactersText.toString() + "</span>";
}

function StringBuffer() { 
   this.buffer = []; 
 } 

 StringBuffer.prototype.append = function append(string) { 
   this.buffer.push(string); 
   return this; 
 }; 

 StringBuffer.prototype.toString = function toString() { 
   return this.buffer.join(""); 
 }; 

var isDescending        = true;
var isWordDescending    = false;

function sortByCount(a,b)
{
    if ( a.count == b.count )
        return sortByWord(a,b);
        
    if ( isDescending )
        return b.count - a.count;
    else
        return a.count - b.count;
}

function sortByWord(a,b)
{
    if ( isWordDescending )
        return ( b.word < a.word ) ? -1 : 1;
    else
        return ( a.word < b.word ) ? -1 : 1;
}

function sortByAdverb(a,b)
{
    if ( a.isAdverb == b.isAdverb )
        return sortByCount(a,b);
        
    if ( isDescending )
        return ( a.isAdverb > b.isAdverb ) ? -1 : 1;
    else
        return ( b.isAdverb > a.isAdverb ) ? -1 : 1;
}

function sortByLarge(a,b)
{
    if ( a.isLarge == b.isLarge )
        return sortByCount(a,b);
        
    if ( isDescending )
        return ( a.isLarge > b.isLarge ) ? -1 : 1;
    else
        return ( b.isLarge > a.isLarge ) ? -1 : 1;
}

function sortByPhrase(a,b)
{
    if ( a.wordType == b.wordType )
        return sortByCount(a,b);
        
    if ( isDescending )
        return ( a.wordType < b.wordType ) ? -1 : 1;
    else
        return ( b.wordType < a.wordType ) ? -1 : 1;
}

function sortByFO(a,b)
{
    if ( a.isFO == b.isFO )
        return sortByCount(a,b);
        
    if ( isDescending )
        return ( a.isFO > b.isFO ) ? -1 : 1;
    else
        return ( b.isFO > a.isFO ) ? -1 : 1;
}

function sortByCharacters(a,b)
{
    if ( a.wordLength == b.wordLength )
        return sortByCount(a,b);
        
    if ( isDescending )
        return b.wordLength - a.wordLength;
    else
        return a.wordLength - b.wordLength;
}

var regLy = null;
function endsWithLy( str )
{
    if ( regLy == null )
        regLy = new RegExp("ly$");
    return regLy.test(str);
}

function removeFormatting( str )
{
    str = str.toLowerCase();
    str = str.replace( /[^\w\s\.@-]/g, '' );
    str = str.replace( /--/g, '' );
    str = str.replace( /\./g, '' );
    str = str.replace( /\s+/g, ' ' );
    return str;
}

function addCommas(nStr)
{
    nStr += '';
    x = nStr.split('.');
    x1 = x[0];
    x2 = x.length > 1 ? '.' + x[1] : '';
    var rgx = /(\d+)(\d{3})/;
    while (rgx.test(x1)) {
        x1 = x1.replace(rgx, '$1' + ',' + '$2');
    }
    return x1 + x2;
}

function readLists()
{
    foList = readList( document.getElementById( 'foList' ).value );
    cwList = readList( document.getElementById( 'cwList' ).value );
    pList = readList( document.getElementById( 'pList' ).value );
}

function readList( listText )
{
    listText = listText.toLowerCase();
    
    listText = listText.replace( /\r/g, '\n' );
    listText = listText.replace( /\n\n/g, '\n' );
    
    var lines   = listText.split( '\n' );
    var list    = { };
    
    var wld;
    for ( var i = 0; i < lines.length; i++ )
    {
        wld = new wordListData( lines[i].toString() );
        
        for ( var j = 0; j < wld.wordList.length; j++ )
            list[wld.wordList[j].toString()] = wld;
    }
    
    return list;
}