(function () {
    'use strict';

    angular.module('cla.poll')
        .service('pollActions', pollActions);

    pollActions.$inject = ['pollTracker', 'pollResources', 'pollRedirect', 'growl.service'];

    /**
     *
     * @constructor
     */
    function pollActions(pollTracker, pollResources, pollRedirect, growlService) {
        var service = {
            preview: false,
            setPreview: setPreview,

            start: start,
            finish: finish,
            next: next,
            getResults: getResults
        };

        return service;

        /**
         * sets preview mode on the resources service.
         */
        function setPreview(preview) {
            service.preview = preview;
            preview ? pollResources.enableInterceptor() : pollResources.disableInterceptor();
        }

        /**
         * start the poll
         * @param {int} poll_id
         * @param {int} anonymous
         * @param {function} callback
         */
        function start(poll_id, anonymous, callback) {
            var payload = {};
            payload.anonymous = anonymous;

            if (!pollTracker.loaded) {
                // get questions
                pollResources.startPoll(poll_id, payload).$promise.then(function (data) {
                    // promise success
                    pollTracker.init(data.questions, data.answers);
                    pollTracker.update();

                    if (!service.preview)
                        pollTracker.attempt_id = data.attempt.id;
                    else
                        pollTracker.attempt_id = 0;

                    // drop out to the callback
                    if (callback && typeof callback === 'function') {
                        callback(data);
                    }
                }, function (response) {
                    // promise failure
                    if (response.data.message) {
                        growlService.flash(response.data.message, null, true);
                    }
                });
            } else if (callback && typeof callback === 'function') {
                // poll already initialised. simply drop out to the callback
                callback();
            }
        }

        /**
         * finish the poll
         * @param {int} attempt_id
         * @param {function} callback
         */
        function finish(attempt_id, callback) {
            // do we have a payload. (i.e. do we have a chosen option)
            var payload = pollTracker.chosen[pollTracker.question];

            if (!payload)
            {
                payload = {};
            }

            // set extra payload params
            payload['complete'] = true;

            // execute finish poll
            pollResources.finishPoll(attempt_id, payload).$promise.then(function (data) {
                if (data.status === undefined)
                {
                    growlService.flash('An error occurred', null, true);
                    return;
                }
                if (data.status === 1) {
                    // set results object
                    pollTracker.results = data.results;
                    pollTracker.can_retake = data.can_retake;
                    pollTracker.attempt_id = data.attempt_id;
                }

                if (callback && typeof callback === 'function') {
                    callback(data);
                }
            }, function (response) {
                growlService.flash('An error occurred, try again', null, true);
            });
        }

        function getResults(poll_id, callback) {
            // set extra payload params
            var payload = {};

            // execute finish poll
            pollResources.getResults(poll_id).$promise.then(function (data) {
                if (data.status === 1) {
                    // set results object
                    pollTracker.results = data.results;
                }

                if (callback && typeof callback === 'function') {
                    callback(data);
                }
            }, function (response) {
                pollRedirect.toPoll(poll_id, response.data.message, true);
            });

        }

        /**
         * move to the next question and submit the user's answer
         * @param {int} poll_id
         * @param anonymous
         */
        function next(poll_id, anonymous) {
            // do we want to update the user attempt?
            if (pollTracker.currentQuestion) {
                var question = pollTracker.question;

                // do we have a payload. (i.e. do we have a chosen option)
                if (pollTracker.chosen[question]) {
                    // evaluate question timer and update payload
                    var time_at_set = Date.now() - pollTracker.timer;
                    pollTracker.chosen[question].time_taken = time_at_set;
                    pollTracker.chosen[question].question_id = pollTracker.currentQuestion.id;
                    pollTracker.chosen[question].anonymous = anonymous;

                    var payload = pollTracker.chosen[question];
                    var answer_array = [];
                    answer_array.push(payload);

                    var promise;
                    (function (index) {
                        // submit payload for current poll and question
                        promise = pollResources.submitQuestion(pollTracker.attempt_id, answer_array)
                            .$promise;
                        promise.then(function (data) {
                                // attempt has come back. add an argument to this callback to retrieve json data.
                                pollTracker.chosen[index].submitted = true;
                            },
                            function (response) {
                                // pollRedirect.toPoll(poll_id, response.data.message, true);
                            }
                        );
                    })(question);
                    return promise;
                }
            }

            return false;
        }
    }
}());
