// Problem generator for arithmetic operation problems
// Creates problem generators for quizzes on arithmetic operations..
//
// Usage:
// The module exports the function "getMathProblemGenerator" It returns an object
// that can be used to generate random questions on math operations.
// The argument should be an object of the form:
//   {operator: string, minValue: number, maxValue: number, template: string(optional)}
//
// The object returned has the following structure:
//
//             {
//                 minValue,      // The minimum value that will be used in problems
//                 maxValue,      // The maximum value that will be used in problems
//                 operator,      // The operator used in problems ("+", "-", "*" or "/")
//                 correctAnswer, // When a new random problem is generated, this is set to the value
//                                // of the correct answer, converted to a string. If you need to use it
//                                // as a number you should use Number() to convert it.
//                 getProblem,    // The function that returns a random problem as a text string.
//                 checkAnswer,   // A function that checks an answer for correctness against the last \
//                                // problem generated. The argument can be a number or a string. The
//                                // function returns true if correct and false if incorrect.
//                 template,      // If the optional argument "template" was used, it is stored here.
//                                // If the argument was not used, this property will not be present.
//                                // If provided, this string is used instead of the default format
//                                // when the problem is generated. {1} and {2} should be used where the
//                                // first and second number in the problem should appear.
//                                // For instance, if the template is "What is {1} X {2}?" then the
//                                // generated problems will look like "What is 5 X 4?
//             };
//
// The user has a choice of using the value of correctAnswer to check or using the checkAnswer function.
//
// Example:
//    let problemGen = getMathProblemGenerator({operator:"+", minValue: 2, maxValue: 9});
//
//    let problemText = problemGen.getProblem();
//    $("#problemBox").html(problemText);
//
//    When the user enters an answer then they might check it this way:
//
//    let answer = $("#answerBox").text();
//    if (problemGen.checkAnswer(answer)) {
//       ...tell user answer was correct
//    }
//    else {
//       ...tell user answer was incorrect
//    }
//
//    Alternatively we could instead have written:
//    if (answer === problemGen.correctAnswer) {
//       etc.
//
//    In this case calls to problemGen.getProblem would generate strings like:
//       "What is 2 * 4?"
//    or
//       "What is 8 * 7?"
// Note: the "correctAnswer" property will be overwritten every time getProblem is called so
// you have to either check the answer or store the value of correctAnswer before calling
// getProblem again.
// If the optional

function randomInt(min, max) {
    if (min > max) {
        console.log(`randomInt given invalid interval (${min}, ${max})`);
        return null;
    }
    return Math.floor(Math.random() * (max - min + 1) + min);
}

function getProblem() {
    let choose1;
    let choose2;
    let choose3;
    let problem;
    let template = this?.template ?? null;

    switch(this.operator) {
        case "+":
        case "plus":
        case "add":
            choose1 = randomInt(this.minValue1, this.maxValue1);
            choose2 = randomInt(this.minValue2, this.maxValue2);
            choose3 = choose1 + choose2;
            problem = this?.template?.replace("{1}", choose1.toString())?.replace("{2}", choose2) ??
                "What is " + choose1 + " + "  + choose2 + " ?";
            this.correctAnswer = choose3.toString();
            break;
        case "-":
        case "minus":
        case "subtract":
            choose1 = randomInt(this.minValue1, this.maxValue1);
            choose2 = randomInt(this.minValue2, Math.min(choose1, this.maxValue2));

            choose3 = choose1 - choose2;
            problem =  this?.template?.replace("{1}", choose1.toString())?.replace("{2}", choose2) ??
                "What is " + choose1 + " - "  + choose2 + " ?";
            this.correctAnswer = choose3.toString();
            break;
        case "*":
        case "times":
        case "multiply":
            choose1 = randomInt(this.minValue1, this.maxValue1);
            choose2 = randomInt(this.minValue2, this.maxValue2);
            choose3 = choose1 * choose2;
            problem =  this?.template?.replace("{1}", choose1.toString())?.replace("{2}", choose2) ??
                "What is " + choose1 + " * "  + choose2 + " ?";
            this.correctAnswer = choose3.toString();
            break;
        case "/":
        case "divided by":
        case "divide":
            choose2 = randomInt(this.minValue2, this.maxValue2);
            choose3 = randomInt(Math.ceil(this.minValue1/choose2), Math.floor(this.maxValue1/choose2));
            choose1 = choose2 * choose3;
            problem =  this?.template?.replace("{1}", choose1.toString())?.replace("{2}", choose2) ??
                "What is " + choose1 + " &divide; "  + choose2 + " ?";
            this.correctAnswer = choose3.toString();
            break;
    }

    return problem;
}

function checkAnswer(ans) {
    return ans.toString() === this.answer;
}
function getMathProblemGenerator({operator, minValue, maxValue, minValue1, maxValue1, minValue2, maxValue2, template}) {
    const problem = {
        operator,
        correctAnswer: "",
        getProblem,
        checkAnswer
    };
    problem.maxValue1 = maxValue1 ?? maxValue;
    problem.maxValue2 = maxValue2 ?? maxValue;
    problem.minValue1 = minValue1 ?? minValue;
    problem.minValue2 = minValue2 ?? minValue;

    // "template" argument is optional
    if (template !== undefined) {
        problem.template = template;
    }
    return problem;
}

export {getMathProblemGenerator};