import { evaluateRoll } from './DSARoll'

const RollWithMockResults = (a, b, c) => {
    return class Roll {

        constructor(formula, actorData) {

        }

        async evaluate() {

            return new Promise(resolve => {

                resolve({
                    terms: [{
                        results: [
                            {
                                result: a,
                                active: true
                            },
                            {
                                result: b,
                                active: true
                            },
                            {
                                result: c,
                                active: true
                            }
                        ]
                    }]
                })

            })

        }


    }
}

const owner = {
    getRollData: () => {
    }
}

describe('Attribute Checks', () => {

    it('should yield a success when the Roll is below the used attribute', async () => {

        let actual = await evaluateRoll("1d20",{
            value: 0,
            werte: [12],
            owner
        }, RollWithMockResults(12))

        expect(actual.tap).toBeGreaterThanOrEqual(0)
    })

    it('should yield a failure when the Roll is above the used attribute', async () => {

        let actual = await evaluateRoll("1d20",{
            value: 0,
            werte: [12],
            owner
        }, RollWithMockResults(13))

        expect(actual.tap).toBeLessThan(0)
    })

    it('should yield a Patzer when the Roll does meet the Patzer Threshold', async () => {

        let actual = await evaluateRoll("1d20",{
            value: 0,
            werte: [12],
            owner
        }, RollWithMockResults(20))

        expect(actual.tap).toBeLessThan(0)
        expect(actual.patzer).toBe(true)
    })

    it('should yield a Meisterlich when the Roll does meet the Meisterlich Threshold', async () => {

        let actual = await evaluateRoll("1d20",{
            value: 0,
            werte: [12],
            owner
        }, RollWithMockResults(1))

        expect(actual.tap).toBeGreaterThanOrEqual(0)
        expect(actual.meisterlich).toBe(true)
    })

})

describe('Skill Checks', () => {

    it('should yield positive TAP when the die roll matches values of used attributes', async () => {
        let taw = 5
        let actual = await evaluateRoll("3d20",{
            value: taw,
            werte: [12, 12, 12],
            owner
        }, RollWithMockResults(12, 12, 12))

        expect(actual.tap).toBe(taw)
    })

    it('should succeed with a TaP* of 1 when the die roll are exactly the values of used attributes', async () => {

        let actual = await evaluateRoll("3d20",{
            value: 0,
            werte: [12, 12, 12],
            owner
        }, RollWithMockResults(12, 12, 12))

        expect(actual.tap).toBe(1)
        expect(actual.patzer).toBe(false)
    })

    it('should fail with negative TaP* when the die roll are above the values of used attributes', async () => {

        let actual = await evaluateRoll("3d20",{
            value: 0,
            werte: [12, 12, 12],
            owner
        }, RollWithMockResults(13, 13, 13))

        expect(actual.tap).toBe(-3)
    })

    it('should yield a Patzer when the die roll does meet the Patzer Threshold', async () => {

        let actual = await evaluateRoll("3d20",{
            value: 1,
            werte: [12, 12, 12],
            owner
        }, RollWithMockResults(20, 20, 20))

        expect(actual.tap).toBeLessThan(0)
        expect(actual.patzer).toBe(true)
    })

    it('should yield a Patzer when the die roll does meet a modified Patzer Threshold', async () => {

        let actual = await evaluateRoll("3d20",{
            value: 1,
            werte: [12, 12, 12],
            countToPatzer: 2,
            owner
        }, RollWithMockResults(20, 20, 1))

        expect(actual.tap).toBeLessThan(0)
        expect(actual.patzer).toBe(true)
    })

    it('should yield a Meisterlich when the die roll does meet the Meisterlich Threshold', async () => {

        const tap = 5

        let actual = await evaluateRoll("3d20",{
            value: tap,
            werte: [12, 12, 12],
            owner
        }, RollWithMockResults(1, 1, 1))

        expect(actual.tap).toBe(tap)
        expect(actual.meisterlich).toBe(true)
    })

    it('should yield a Meisterlich when the die roll does meet the modified Meisterlich Threshold', async () => {

        const tap = 5

        let actual = await evaluateRoll("3d20",{
            value: tap,
            werte: [12, 12, 12],
            countToMeisterlich: 2,
            owner
        }, RollWithMockResults(1, 20, 1))

        expect(actual.tap).toBe(tap)
        expect(actual.meisterlich).toBe(true)
    })

    it('should yield a success when the die roll can be buffered with TaP', async () => {

        let actual = await evaluateRoll("3d20",{
            value: 8,
            werte: [12, 12, 12],
            owner
        }, RollWithMockResults(15, 15, 8))

        expect(actual.tap).toBe(2)
    })

    it('should yield a failure when the die roll is above the reduced attributes', async () => {

        let actual = await evaluateRoll("3d20",{
            value: 0,
            mod: -3,
            werte: [12, 12, 12],
            owner
        }, RollWithMockResults(10, 10, 10))

        expect(actual.tap).toBe(-3)
    })

    it('should yield a success when the die roll is below the reduced attributes', async () => {

        let actual = await evaluateRoll("3d20",{
            value: 0,
            mod: -1,
            werte: [12, 12, 12],
            owner
        }, RollWithMockResults(11, 11, 11))

        expect(actual.tap).toBe(1)
    })

})
