interface TestingOptions {
    name : string;
    value : number;
}

class Dice {
    protected range : Array<number> = [0, 0, 1, 1];
    public minResult = 0;
    protected testString : string;

    public constructor (testString : string) {
        this.testString = testString;
    }

    public roll (stat : number) : Array<number>  {
        let rng = this.range.slice();
        if (stat >= 10) {
            rng.push(2, 1);
        } else if (stat >= 7) {
            rng.push(1, 1);
        } else if (stat >= 4) {
            rng.push(1);
        }
        let results = [];
        for (let i = 0; i < stat; i++) {
            let index = Math.floor(Math.random() * (rng.length));
            results.push(rng[index]);
        }

        // TODO: Print the dice results if Memory.ShowDice = 1

        return results;
    }

    public static sum (a, b) {
        return a + b;
    }

    public getSay (results : Array<number>) : Say {
        let finalResult = results.reduce(Dice.sum);
        return new Say(
            new SayBold("[", this.testString, "] "),
            " = [", results.join("] ["), "]",
            results.length == 1 ? "" :
                (" = " + finalResult)
        );
    }

    public static testAgainstRoll (player : TestingOptions, enemy : TestingOptions) : number {
        let playerDice = new Dice(player.name);
        let playerResult = playerDice.roll(player.value);
        let enemyDice = new Dice(enemy.name);
        let enemyResult = enemyDice.roll(enemy.value);

        return playerResult.reduce(Dice.sum) - enemyResult.reduce(Dice.sum);
    }

    public static testAgainstDifficulty (player : TestingOptions, difficulty : number) : number {
        let playerDice = new Dice(player.name);
        let playerResult = playerDice.roll(player.value);
        return playerResult.reduce(Dice.sum) - difficulty;
    }
}