/**
 * Tracker service test cases
 * @author Simon Willan <simon.willan@claromentis.com>
 */
(function () {
    'use strict';

    describe('Tracker service', function () {

        var quizTracker, answers, questions;

        // load app
        beforeEach(angular.mock.module('cla.quiz'));

        beforeEach(angular.mock.inject(function ($injector) {
            quizTracker = $injector.get('quizTracker');

            // fake questions list
            questions = [
                {id: '1', text: 'Why is a raven like a writing desk?', options: {1: {}, 2: {}, 3: {}}},
                {id: '2', text: 'What is the speed of dark as night falls?'},
                {id: '3', text: 'What\'s the difference between a duck?'},
                {
                    id: '4',
                    text: 'If the square on the hypotenuse equals the sum of the square on the other two sides, then why is a mouse when it spins?'
                }
            ];

            answers = {
                "1": {
                    "properties": {
                        "response": {
                            "2": "Because there is a B in both and an N in neither"
                        },
                        "time_taken": "448"
                    }
                },
                "2": {
                    "properties": {
                        "response": {
                            "7": "One of its eyes are left to right."
                        },
                        "time_taken": "2057"
                    }
                }
            };

            quizTracker.init(questions, answers);
            quizTracker.loaded = false;
        }));

        it('should exist', function () {
            expect(quizTracker).toBeDefined();
        });

        // test init() method
        describe('.init()', function () {

            it('should set any already chosen options, given as an argument to init()', function () {

                var chosen = {
                    "0": {
                        options: [2],
                        time_taken: 448,
                        submitted: true
                    },
                    "1": {
                        options: [7],
                        time_taken: 2057,
                        submitted: true
                    }
                }

                // test that quiz tracker chosen property is the same as the test chosen object
                expect(quizTracker.chosen).toEqual(chosen);
            });

            it('should preset the first question to be the last unanswered ' +
                'question when continuing a quiz', function () {

                // expect question to start on question 3 (index 2)
                expect(quizTracker.question).toBe(2);

            });

        });

        // test update() performs the correct tasks on the tracker object
        describe('.update()', function () {

            it('should change \'current\' question object, to whatever the newly selected question is', function () {

                quizTracker.current = quizTracker.questions[quizTracker.question];
                quizTracker.question = 1;

                // run update
                quizTracker.update();

                // expect the new current to equal the second question in the fake list.
                expect(quizTracker.current).toEqual(quizTracker.questions[1]);
            });

        });

        // test that next() updates the question to the next in the list
        describe('.next()', function () {

            it('should progress the quiz index by 1, and make sure the current object is updated to reflect this.', function () {

                // reset question
                quizTracker.question = 0;

                quizTracker.next();
                expect(quizTracker.question).toBe(1);
                expect(quizTracker.current).toEqual(quizTracker.questions[1]);
            });

        });

        // test that prev() updates the question to the previous in the list
        describe('.prev()', function () {

            it('should retract the quiz index by 1, and make sure the current object is updated to reflect this.', function () {

                // reset question
                quizTracker.question = 1;

                quizTracker.prev();
                expect(quizTracker.question).toBe(0);
                expect(quizTracker.current).toEqual(quizTracker.questions[0]);
            });

        });

        // test that goto() takes you to a specific question
        describe('.goto()', function () {

            it('should change the current question index and update the current question object', function () {
                quizTracker.goto(2);
                expect(quizTracker.question).toBe(2);
                expect(quizTracker.current).toEqual(quizTracker.questions[2]);
            });

        });

        // test that next and previous are properly clamping the question index
        describe('.clamp()', function () {

            it('should now allow the current question to drop below 0, or be above the maximum count - 1', function () {

                quizTracker.question = 0;

                quizTracker.prev();
                expect(quizTracker.question).toBe(0);

                quizTracker.question = 3;
                quizTracker.next();
                expect(quizTracker.question).toBe(3);
            });

        });

        describe('.track()', function () {

            it('should be able to read a question index from the tracker array', function () {

                // .next() tests that .track() works, however .track()
                quizTracker.question = 0;
                quizTracker.next(1);
                expect(quizTracker.question).toBe(1);

            });

        });

        // option metrics
        describe('answer and option metrics', function () {

            // test whether we can get a count of the number of questions a user has answered
            it('getChosenCount() should return the number of questions a user has answered', function () {

                var answered = quizTracker.getChosenCount();

                expect(answered).toBe(2);
            });

            // test whether we can count the number of options a question has
            it('getOptionsCount() should return the number of options a given question has', function () {

                var num_options = quizTracker.getOptionsCount(0);

                expect(num_options).toBe(3);
            });

            // test if we can find out if an option is chosen for a given question
            it('isOptionChosen() should return true if a given option is selected on a given question', function () {

                // question index 1 (id 2), option id 7 is selected.
                var is_option_chosen = quizTracker.isOptionChosen(1, 7);
                expect(is_option_chosen).toBe(true);

                // question index 0 (id 1),
                var is_option_chosen = quizTracker.isOptionChosen(0, 1);
                expect(is_option_chosen).toBe(false);
            });

            // test if we can get back the first question found that hasn't been answered yet
            it('firstUnansweredQuestion() should return the first question index found in the list of questions, ' +
                'that has yet to be answered', function () {

                var first_unanswered_question = quizTracker.firstUnansweredQuestion();
                expect(first_unanswered_question).toBe(2);
            });

        });

    });

}());
