;(function() {

    var rater = function() {
        var StdLib = window.StdLib;

        var rates = {
            positive: 1,
            negative: 0
        };

        var form = {
            [rates.positive]: {
                title: 'Мы рады, что статья была полезной для вас',
                text: 'Информация на сайте могла устареть, рекомендуем обратиться к юристу для уточнения вашего вопроса.'
            },
            [rates.negative]: {
                title: 'Не нашли ответ на свой вопрос?',
                text: 'Наш юрист проконсультирует вас абсолютно бесплатно по любому вопросу.'
            }
        };

        var selectors = {
            rater: {
                body: '.js-article-rater-body',
                value: '.js-article-rater-control-value',
                control: '.js-article-rater-control',
                error: '.js-article-rater-controls-error',
                success: '.js-article-rater-controls-success',
                self: '.js-article-rater',
                form: {
                    title: '.js-article-rater-lead-form-title',
                    text: '.js-article-rater-lead-form-text'
                }
            }
        };

        var raterNode =  document.querySelector(selectors.rater.self);
        var raterBodyNode = document.querySelector(selectors.rater.body);
        var raterControlsError = document.querySelector(selectors.rater.error);
        var raterControlsSuccess = document.querySelector(selectors.rater.success);
        var raterFormText = document.querySelector(selectors.rater.form.text);
        var raterFormTitle = document.querySelector(selectors.rater.form.title);
        var raterControlsNodes = document.querySelectorAll(selectors.rater.control);
        var raterControlsNodesMap = (function() {
            var nodesMap = {};
            for (var i = 0; i < raterControlsNodes.length; i++) {
                var node = raterControlsNodes[i];
                var rate = node.getAttribute('data-rate');
                nodesMap[rate] = node;
            }
            return nodesMap;
        })();

        var store = StdLib.store.create({
            rate: null,
            isPending: false,
            isSuccess: false,
            isRaterBodyOpen: false,
            rateCounts: {
                [rates.positive]: getInitialRateCount(rates.positive),
                [rates.negative]: getInitialRateCount(rates.negative)
            }
        });

        function allowed() {
            return parseInt(raterNode.getAttribute('data-allowed'), 10);
        }

        function getInitialRateCount(rate) {
            return parseInt(raterControlsNodesMap[rate].querySelector(selectors.rater.value).innerHTML, 10) || 0;
        }

        function togglePendingRaterControlSubscriber(state) {
            var rate = state.rate;
            var isPending = state.isPending;
            var raterControlNode = raterControlsNodesMap[rate];
            var action = isPending ? 'add' : 'remove';
            togglePendingRaterControl(raterControlNode, action);
        }

        function changeRateCountsSubscriber(state) {
            var rate = state.rate;
            var rateCounts = state.rateCounts;
            var raterControlNode = raterControlsNodesMap[rate];
            raterControlNode && (raterControlNode.querySelector(selectors.rater.value).innerHTML = rateCounts[rate]);
        }

        function changeRateSubscriber(state) {
            var rate = state.rate;
            raterFormText && (raterFormText.innerHTML = form[rate].text);
            raterFormTitle && (raterFormTitle.innerHTML = form[rate].title);
        }

        function toggleRaterBodySubscriber(state) {
            var isRaterBodyOpen = state.isRaterBodyOpen;

            isRaterBodyOpen ? $(raterBodyNode).show('slow') : $(raterBodyNode).hide('slow');
        }

        function togglePendingRaterControl(node, action) {
            node && node.classList[action]('article-rater-controls__control--pending');
        }

        function init() {
            for (var i = 0; i < raterControlsNodes.length; i++) {
                var raterControlsNode = raterControlsNodes[i];
                raterControlsNode.addEventListener('click', createRaterControlClickHandler(raterControlsNode));
            }
        }

        function createRaterControlClickHandler(control) {
            return function() {
                raterControlClickHandler(control);
            };
        }

        function raterControlClickHandler(control) {
            var state = store.getState();
            var isRaterBodyOpen = state.isRaterBodyOpen;
            var rate = control.getAttribute('data-rate');

            rate = parseInt(rate, 10);

            asyncRate(rate);
            store.setState({
                isRaterBodyOpen: true,
            });
        }

        function asyncRate(rate) {
            var state = store.getState();
            var isPending = state.isPending;
            var isSuccess = state.isSuccess;
            var rateCounts = state.rateCounts;

            if (isPending || isSuccess) {
                return;
            }

            store.setState({
                isPending: true,
                rate: rate
            });

            var http = new StdLib.Http();

            var data = {
                isPositive: Boolean(rate)
            };

            http.post({
                url: '/api/article/rate/',
                body: JSON.stringify(data),
                headers: {'Content-Type': 'application/json', 'X-CSRFToken': StdLib.сookie('csrftoken')},
                success: function(response) {
                    var data = JSON.parse(response);
                    if (data.status === 'ok') {
                        store.setState({
                            isPending: false,
                            isSuccess: true,
                            rateCounts: StdLib.object.merge(rateCounts, {
                                [rate]: rateCounts[rate] + 1
                            })
                        });

                        $(raterControlsSuccess).show(400);
                        raterControlsNodesMap[rate].classList.add('article-rater-controls__control--active');
                    } else {
                        if (data.status === 'error') {
                            data.message && (raterControlsError.innerHTML = data.message);
                            $(raterControlsError).show(400);
                        }
                    }
                }
            });
        }

        store.subscribe(changeRateSubscriber);
        store.subscribe(toggleRaterBodySubscriber);
        store.subscribe(changeRateCountsSubscriber);
        store.subscribe(togglePendingRaterControlSubscriber);

        allowed() && init();
    };

    document.querySelector('.js-article-rater') && rater();

})();