var TRY_TIMES = 1;
var DEFAULT_RIGHT_MESSAGE = "Correct";
var DEFAULT_WRONG_MESSAGE = "Have another go";
var multipleDelimiter = "*";
var answerDelimiter = "^";


/** javascript functions for question paragraph. form.js is needed. **/

/** */
function onFormItemChange(formItem, num) {
    var theForm = getForm(formItem);
    var instantCheck = getElementValue(theForm.elements["instantCheck"]);
    var feedbackForOptions = getElementValue(theForm.elements["feedbackForOptions"]);

    if (feedbackForOptions != "") {

        var formElement = theForm.elements["q" + num];
        if (formElement.length) {
            var selectedIndex = -1;
            for (var x = 0; x < formElement.length; x++) {
                if (formElement[x].checked) {
                    selectedIndex = x;
                    break;
                }
                if (formElement[x].selected) {
                    selectedIndex = x - 1;
                    break;
                }

            }
            var feedbacks = feedbackForOptions.split(multipleDelimiter);
            if ((selectedIndex != -1) && ( selectedIndex < feedbacks.length )) {
                displayFeedback(theForm, feedbacks[selectedIndex]);
            } else {
                hideFeedback(theForm);
            }
        }
    } else if (instantCheck == "true") {
        if (rightAnswer(theForm, num))
            displayFeedback(theForm, DEFAULT_RIGHT_MESSAGE);
        else
            displayFeedback(theForm, DEFAULT_WRONG_MESSAGE);
    }
}

/** Checks the whole form to see if all answers are right. */
function checkAnswer(theForm) {
    theForm.elements["tryTimes"].value = parseInt(getElementValue(theForm.elements["tryTimes"])) + 1;
    if (theForm.elements["tryTimes"].value >= TRY_TIMES) {
        // display reveal answer button
        theForm.elements["reveal"].style.display = "";
    }

    var answers = getElementValue(theForm.elements["answer"]).split(answerDelimiter);
    if (answers.length > 0) {
        var rightNum = 0;
        var questionNum = 0;
        for (var i = 0; i < answers.length; i++) {
            if (theForm.elements["q" + i]) {
                questionNum++;
                if (rightAnswer(theForm, i)) {
                    rightNum++;
                }
            }
        }
        if (rightNum == questionNum) {          // if all answers are right
            theForm.elements["check"].style.display = "none";
            theForm.elements["reveal"].style.display = "none";
            displayFeedback(theForm, DEFAULT_RIGHT_MESSAGE);
        } else {                                // some answers are right, some are wrong
            displayFeedback(theForm, DEFAULT_WRONG_MESSAGE);
        }
    }
}

/** Reveals answers for the whole form. */
function revealAnswer(theForm) {
    var answers = getElementValue(theForm.elements["answer"]).split(answerDelimiter);
    if (answers.length > 0) {
        for (var i = 0; i < answers.length; i++) {
            var rightAnswers = answers[i].split(multipleDelimiter);
            clearElementValue(theForm.elements["q" + i]);
            for (var x = 0; x < rightAnswers.length; x++)
                setElementValue(theForm.elements["q" + i], rightAnswers[x]);
        }
    }
}

/** Prepares for the form, such as check if all answers are in options, set input box width, etc. */
function prepareForm(theForm) {
    if ((getElementValue(theForm["answer"]) != "") && (getElementValue(theForm["options"]) != "")) {
        var optionArray = getElementValue(theForm["options"]).split(multipleDelimiter);
        var answers = getElementValue(theForm["answer"]).split(answerDelimiter);
    }
    setInputBoxWidth(theForm);
}


/** ---------- PRIVATE FUNCTIONS ---------- */


/** check if answer is right for one single question. */
function rightAnswer(theForm, num) {
    var isRight = false;
    if (theForm) {
        var userInput = getElementValue(theForm.elements["q" + num]);
        var answers = getElementValue(theForm.elements["answer"]).split(answerDelimiter);
        var rightAnswers = answers[num].split(multipleDelimiter);
        // if user inputs multiple answers, such as checkbox, multiple-select
        // they have to match all right answers
        if (userInput instanceof Array) {
            userInput = userInput.sort();
            rightAnswers = rightAnswers.sort();
            if (userInput.length == rightAnswers.length) {
                var isWrong = false;
                for (var i = 0; i < rightAnswers.length; i++) {
                    if (!answerMatch(userInput[i], rightAnswers[i]))
                        isWrong = true;
                }
                if (!isWrong)
                    isRight = true;
            }
        } else {
            // otherwise, if their answer is one of right answers, it's right
            for (var i = 0; i < rightAnswers.length; i++) {
                if (answerMatch(userInput, rightAnswers[i]))
                    isRight = true;
            }
        }
    }
    //if (isRight)
    //    disableElement(theForm.elements["q" + num]);
    return isRight;
}

/** check if answer matches */
function answerMatch(userInput, rightAnswer) {
    // get rid of leading and trailing spaces
    userInput = trimString(userInput);
    // replace 2 spaces with 1 space
    while (userInput.indexOf("  ") != -1)
        userInput = userInput.replace("  ", " ");

    // get rid of leading and trailing spaces
    rightAnswer = trimString(rightAnswer);
    // replace 2 spaces with 1 space
    while (rightAnswer.indexOf("  ") != -1)
        rightAnswer = rightAnswer.replace("  ", " ");

    // alert("#" + userInput + "#" + rightAnswer + "#");

    if (userInput == rightAnswer)
        return true;
    else
        return false;
}

/** sets input box width according answer's length */
function setInputBoxWidth(theForm) {
    var MAXIMIUM_LENGTH = 77;
    var answers = getElementValue(theForm.elements["answer"]).split(answerDelimiter);
    for (var i = 0; i < answers.length; i++) {
        var formItem = theForm.elements["q" + i];
        var formType = getElementType(formItem);
        if (formType == 'text') {
            var rightAnswers = answers[i].split(multipleDelimiter);
            var answerLen = 0;
            for (var j = 0; j < rightAnswers.length; j++) {
                if (rightAnswers[j].length > answerLen)
                    answerLen = rightAnswers[j].length;
            }
            if (answerLen > MAXIMIUM_LENGTH)
                formItem.style.width = ( MAXIMIUM_LENGTH * 8) + "px";
            else
                formItem.style.width = ( (answerLen + 1) * 8) + "px";
        }
    }
}

function displayFeedback(theForm, message) {
    if (getElementValue(theForm.elements["displayFeedback"]) == "popup") {
        alert(message);
    } else {
        // display feedback on page by default
        var feedback = getFeedbackElement(theForm.elements["q0"]);
        if (feedback) {
            feedback.style.display = 'block';
            feedback.firstChild.nodeValue = message;
        }
    }
}

function hideFeedback(theForm) {
    var feedback = getFeedbackElement(theForm.elements["q0"]);
    if (feedback) {
        feedback.style.display = 'none';
    }
}

/** returns parent node of a form item */
function getParentNode(formItem) {
    if (formItem) {
        // if this form item has parent, return its parent
        if (formItem.parentNode) {
            return formItem.parentNode;
        } else if (formItem.length) { // if this form item has length, that means it's a radio group, or checkbox group
            if (formItem[0].parentNode) {    // we just return the first item's parent in this group
                return formItem[0].parentNode;
            }
        }
    }
    return false;
}

/** Returns wrpper element of current form item. A wrapper is the first SPAN tag which current form item is in. */
function getWrapper(formItem) {
    var wrapper = getParentNode(formItem);
    while (wrapper && (wrapper.nodeName != "SPAN"))
        wrapper = wrapper.parentNode;
    return wrapper;
}

/** answer element is the first SPAN after the form item's parent, this element should exist all the time */
function getAnswerElement(formItem) {
    var parent = getWrapper(formItem);
    if (parent) {
        var answerElement = parent.nextSibling;
        // if it's not a SPAN, try next sibling
        while (answerElement && ( answerElement.nodeName != "SPAN")) {
            answerElement = answerElement.nextSibling;
        }
        return answerElement;
    }
    return false;
}

/** feedback element is just after question text */
function getFeedbackElement(formItem) {
    var parent = getWrapper(formItem);
    if (parent && parent.parentNode && parent.parentNode.nextSibling) {
        var feedback = parent.parentNode.nextSibling;
        // if it's not a DIV, try next sibling
        while (feedback && ( feedback.nodeName != "DIV")) {
            feedback = feedback.nextSibling;
        }
        return feedback;
    }
    return false;
}

/** Trims leading and trailing spaces */
function trimString(sInString) {
    // strip leading
    sInString = sInString.replace(/^\s+/g, "");
    // strip trailing
    return sInString.replace(/\s+$/g, "");
}

/** Returns which key has been pressed */
function getKeypress(evt) {
    var keynum;
    if (window.event)
        keynum = evt.keyCode;
    else if (evt.which)
        keynum = evt.which;
    return keynum;
}
