function trim(str) {

    var r = /^\s*(.*\S)\s*$/;
    r.exec( str );
    return (typeof( RegExp.$1 ) != "undefined") ? RegExp.$1 : "";
};

function processValue(groupName, valueName, groupReport, mode) {

    var answer = this.form[valueName+"ans"];
    var shouldBeChecked = (answer && answer.value == "on") ? true : false;
    var status;        
    var altInfo = "";

    if( this.form[valueName+"type"] && this.form[valueName+"type"].value == "text" ) {
        var value = trim(this.form[valueName].value);
        if( value ) {
            groupReport.isComplete = true;

            var answer = "";
            if( this.form[valueName+"ans"] )
                answer = trim(this.form[valueName+"ans"].value);

            altInfo = "ANSWER: "+answer;

            if( !this.form[valueName+"casesensitive"]
                 ||
                this.form[valueName+"casesensitive"].value != "yes" ) {
                value = value.toLowerCase();    
                answer = answer.toLowerCase();
            }
    
            status = ( value == answer ) ? "correct" : "incorrect";
        } else {
            status = "incomplete";
        }
    } else {
        var input = this.form[groupName];
        if( typeof(input.length) != "undefined" ) {

            var inputArray = (typeof(this.form[groupName].options) != "undefined")
                              ? this.form[groupName].options : input;
        
            for( var i = 0; i < inputArray.length; i++ ) {

                if( inputArray[i].value == valueName ) {
                    input = inputArray[i];
                    break;
                }
            }
        }
    
        if( typeof(input.checked) != "undefined" )
            isOn = input.checked;
        else {
            isOn = input.selected;
            if( shouldBeChecked )
                groupReport.altInfo = "ANSWER: "+input.text;
        }
    
        if( isOn || groupReport.selectionType == "multiple" )
            groupReport.isComplete = true;

        if( shouldBeChecked  )
            status = isOn ? "correctly_checked" : "missed";
        else    
            status = isOn ? "incorrectly_checked" : "correctly_unchecked";
    }

    var score = 1;
    if( this.form[valueName+"scoreweight"] )
        score = this.form[valueName+"scoreweight"].value;

    if( groupReport.selectionType == "multiple"
         ||
        score > groupReport.maxScore )
        groupReport.maxScore += score;
 
    if( status == "correctly_checked" || status == "correct" 
         ||
        (status == "correctly_unchecked" && groupReport.selectionType == "multiple")) {
        groupReport.score += score;
    }

    var gif = document[valueName+"gif"];
    if( gif ) {
        if( altInfo )
            gif.alt = altInfo;
        if( mode == "clearinfo" ) {
            gif.alt = "";
            gif.src = this.form["resourceURL"].value+"ansblank.gif";
        } else
            if( mode == "completeness" ) {
                if( status == "incomplete" )
                    gif.src = this.form["resourceURL"].value+"ansincmp.gif";
                else
                    gif.src = this.form["resourceURL"].value+"ansblank.gif";
            } else
                switch( status ) {
                    case "correctly_unchecked":
                        if( groupReport.selectionType == "multiple" ) {
                            gif.alt = "OK";
                            gif.src = this.form["resourceURL"].value+"ansright.gif";
                        }
                        break;            
                    case "correct":
                    case "correctly_checked":
                        gif.alt = "OK";
                        gif.src = this.form["resourceURL"].value+"ansright.gif";
                        break;            
                    case "missed":
                        gif.alt = "THIS WAS THE RIGHT ANSWER";
                        gif.src = this.form["resourceURL"].value+"ansmissd.gif";
                        break;            
                    case "incorrectly_checked":
                    case "incorrect":
                        if( !altInfo )
                            gif.alt = "INCORRECT";
                        gif.src = this.form["resourceURL"].value+"answrong.gif";
                        break;            
                    case "incomplete":
                        gif.src = this.form["resourceURL"].value+"ansincmp.gif";
                        break;            
                    default:
                        gif.src = this.form["resourceURL"].value+"ansblank.gif";
                }
    }

    switch( status ) {
        case "correctly_unchecked":
        case "correct":
        case "correctly_checked":
            return "correct";    
        default:
            return "incorrect";    
    }
}

function processGroup(groupName, questionReport, mode) {

    var valueNames = this.form[groupName+"values"].value.split(" ");
    var status;

    var selectionType = "exclusive";
    if( this.form[groupName+"selection"]
         &&
        this.form[groupName+"selection"].value == "multiple" )
        selectionType = "multiple";    

    status = "correct";
    var groupReport = new GroupReport(selectionType);
    for( var i = 0; i < valueNames.length; i++ ) {
        var valueName = valueNames[i];
        var valueStatus = this.processValue(groupName, "value"+valueName, groupReport, mode);
        if( valueStatus == "incorrect" )
            status = valueStatus;
    }
    if( !groupReport.isComplete )
        questionReport.isComplete = false;

    var scoreWeight = 1;
    if( this.form[groupName+"scoreweight"] )
        scoreWeight = Number(this.form[groupName+"scoreweight"].value);

    var score;
    var maxScore;
    if( this.form[groupName+"subscoring"]
         &&
        this.form[groupName+"subscoring"].value == "no" ) {
        maxScore = scoreWeight;
        score = (status == "correct" ) ? maxScore : 0;
    } else {
        score = groupReport.score * scoreWeight;
        maxScore = groupReport.maxScore * scoreWeight;
    }

    questionReport.maxScore += maxScore;
    questionReport.score += score;

    if( status == "incorrect" )
        questionReport.status = status;

    var gif = document[groupName+"gif"];
    if( gif ) {
        if( groupReport.altInfo )
            gif.alt = groupReport.altInfo;
        if( mode == "clearinfo" ) {
            gif.alt = "";
            gif.src = this.form["resourceURL"].value+"ansblank.gif";
        } else
            if( mode == "completeness" ) {
                if( groupReport.isComplete )
                    gif.src = this.form["resourceURL"].value+"ansblank.gif";
                else
                    gif.src = this.form["resourceURL"].value+"ansincmp.gif";
            } else {
                if( !groupReport.isComplete )
                    gif.src = this.form["resourceURL"].value+"ansincmp.gif";
                else
                    if( status == "correct" )
                        gif.src = this.form["resourceURL"].value+"ansright.gif";
                    else
                        gif.src = this.form["resourceURL"].value+"answrong.gif";
            }
    }

    return status;
}

function processQuestion(questionNum, quizReport, mode) {

    var groupNames = this.form["question"+questionNum+"groups"].value.split(" ");
    var status;
    var altInfo = "";

    var questionReport = null;
    if( quizReport ) {
        var questionNumStr;
        if( this.form["question"+questionNum+"numberstr"] )
            questionNumStr = this.form["question"+questionNum+"numberstr"].value;
        else
            questionNumStr = "Question " + questionNum;
        questionReport = new QuestionReport(questionNumStr);
    }

    status = "correct";
    for( var i = 0; i < groupNames.length; i++ ) {
        var groupStatus = this.processGroup("group"+groupNames[i],questionReport,mode);
        if( groupStatus == "incorrect" )
            status = groupStatus;
    }

    if( quizReport ) {

        var scoreWeight = 1;
        if( this.form["question"+questionNum+"scoreweight"] )
            scoreWeight = Number(this.form["question"+questionNum+"scoreweight"].value);

        if( this.form["question"+questionNum+"subscoring"]
             &&
            this.form["question"+questionNum+"subscoring"].value == "no" ) {
            questionReport.maxScore = scoreWeight;
            questionReport.score = (status == "correct" ) ? questionReport.maxScore : 0;
        } else {
            questionReport.score *= scoreWeight;
            questionReport.maxScore *= scoreWeight;
        }

        altInfo = "SCORE: "+questionReport.score+" of "+questionReport.maxScore;

        quizReport.questionReports[quizReport.questionReports.length] = questionReport;

        quizReport.totalMaxScore += questionReport.maxScore;
        quizReport.totalScore += questionReport.score;
    }

    var gif = document["question"+questionNum+"gif"];
    if( gif ) {
        if( altInfo )
            gif.alt = altInfo;
        if( mode == "clearinfo" ) {
            gif.alt = "";
            gif.src = this.form["resourceURL"].value+"blank.gif";
        } else
            if( mode == "completeness" ) {
                if( questionReport.isComplete )
                    gif.src = this.form["resourceURL"].value+"complete.gif";
                else
                    gif.src = this.form["resourceURL"].value+"incomplt.gif";
            } else {
                if( !questionReport.isComplete )
                    gif.src = this.form["resourceURL"].value+"incomplt.gif";
                else
                    if( status == "correct" )
                        gif.src = this.form["resourceURL"].value+"correct.gif";
                    else
                        gif.src = this.form["resourceURL"].value+"incorrct.gif";
            }
    }

    return status;
}

function processQuestions(quizReport, mode) {

    var questionNum = this.form["questionnum"].value;
    
    if( questionNum ) {
        for( var i = 0; i < questionNum; i++ ) {
            this.processQuestion(i+1, quizReport, mode);            
        }    
    }
}

function processQuiz(mode) {

    var quizReport = new QuizReport(this);
    this.processQuestions(quizReport,mode);
    if( mode != "clearinfo" )
        quizReport.displayReport(mode);
}

function TH(content) {
    return '<TH CLASS="QSTableHeadCell">'+content+'</TH>';
}

function displayReport(mode) {

    var reportWindow = window.open('','ReportWindow','height=450,width=400,scrollbars=yes')

    reportWindow.document.write('<HTML>');
    reportWindow.document.write('<BODY CLASS="QSBody"><HEAD><TITLE>Quiz Summary</TITLE>');
    
    if( this.formHandler.form["cssStyleURL"] ) {
        var cssStyleURL = this.formHandler.form["cssStyleURL"].value;
        reportWindow.document.write('<LINK REL=STYLESHEET HREF="'+cssStyleURL+'" TYPE="text/css">');
    }

    reportWindow.document.write('</HEAD><H2 CLASS="QSTitle">Quiz Summary</H2>')
    reportWindow.document.write('<TABLE CLASS="QSTable" WIDTH="90%" CELLPADDING="5">')

    reportWindow.document.write('<TR CLASS="QSTableRow">');
    if( mode == "completeness" )
        reportWindow.document.write(TH("")+TH("Status"));
    else
        reportWindow.document.write(TH("")+TH("Status")+TH("Score")+TH("Max Score"));

    for( var i = 0; i < this.questionReports.length; i++ ) {
        var qR = this.questionReports[i];
        reportWindow.document.write('<TR><TD CLASS="QSQuestionNumCell">'+qR.numberStr+'</TD>' );

        var gifURL;
        if( mode == "completeness" ) {
            if( qR.isComplete )
                gifURL = this.formHandler.form["resourceURL"].value+"complete.gif";
            else
                gifURL = this.formHandler.form["resourceURL"].value+"incomplt.gif";
        } else
            if( !qR.isComplete )
                gifURL = this.formHandler.form["resourceURL"].value+"incomplt.gif";
            else
                if( qR.status == "correct" )
                    gifURL = this.formHandler.form["resourceURL"].value+"correct.gif";
                else
                    gifURL = this.formHandler.form["resourceURL"].value+"incorrct.gif";

        reportWindow.document.write('<TD CLASS="QSStatusCell"><IMG SRC="'+gifURL+'"></TD>');
        if( mode != "completeness" ) {
           reportWindow.document.write('<TD CLASS="QSScoreCell" ALIGN="right">'+qR.score+'</TD>');
           reportWindow.document.write('<TD CLASS="QSMaxScoreCell" ALIGN="right">'+qR.maxScore+'</TD>');
        }
        reportWindow.document.write('</TR>');
    }

    if( mode != "completeness" ) {
        var pcent = Math.round((1000 * this.totalScore) / this.totalMaxScore) / 10;

        reportWindow.document.write
         ('<TR CLASS="QSTotalRow"><TD CLASS="QSTotalCell" COLSPAN="4">Total score: '
          +this.totalScore+' of '+this.totalMaxScore+' ('+pcent+'%)</TD></TR>');
    }


    reportWindow.document.write('</TABLE>');

    reportWindow.document.write('</BODY></HTML>');
    reportWindow.document.close();
    reportWindow.focus();
}

function QuizReport(formHandler) {
    this.formHandler     = formHandler;
    this.questionReports = new Array();
    this.displayReport   = displayReport;
    this.totalMaxScore   = 0;
    this.totalScore      = 0;
}

function QuestionReport(numberStr) {
    this.numberStr  = numberStr;
    this.maxScore   = 0;
    this.score      = 0;
    this.status     = "correct";
    this.isComplete = true;
}

function GroupReport(selectionType) {
    this.selectionType = selectionType;
    this.score         = 0;
    this.maxScore      = 0;
    this.status        = "correct";
    this.isComplete    = false;
    this.altInfo       = "";
}

function FormHandler(form) {

    this.form             = form;
    this.processValue     = processValue;
    this.processGroup     = processGroup;
    this.processQuestion  = processQuestion;
    this.processQuestions = processQuestions;
    this.processQuiz      = processQuiz;
}
