(function(w, d){

    function telegramLoginBegin()
    {
        w.voteShowModal('Получение данных...');

        const FD = new FormData();
        FD.append(d.querySelector('meta[name=csrf-param]').getAttribute('content'), d.querySelector('meta[name=csrf-token]').getAttribute('content'));

        fetch('/telegram-webhook/login-button', {
            method: 'post',
            body: FD,
        }).then(function(res) {
            return res.json();
        }).then(function(json) {
            if (!json) {
                return;
            }

            var btn = document.createElement('a');
            btn.target = '_blank';
            btn.innerText = 'Войти через Telegram';
            btn.classList.add('app-btn');
            btn.addEventListener('click', onTelegramLogin);
            btn.href= json.buttonLink;

            w.voteShowModal('После нажатия кнопки вы перейдете в диалог с нашим ботом @aicomics_bot.<br><br>В диалоге с ботом нажмите кнопку Start<br><br>', btn);

        });


    }


    function onTelegramLogin(event)
    {
        var currentIteration = 0;
        var telegramLoginInterval;

        telegramLoginInterval = setInterval(function(){

            fetch('/vote/socialuser/telegram-auth-check')
                .then(function(data){
                    return data.json()
                })
                .then(function(json){

                    if (json.ok) {

                        clearInterval(telegramLoginInterval);

                        if (w.localStorage) {
                            w.localStorage.setItem('snloginsuccess', '1');
                        }
                        location.reload();

                    }

                    if (currentIteration > 50) {

                        clearInterval(telegramLoginInterval)



                    }

                    console.log(currentIteration);

                })


        }, 3000);
    }

    function onSnLogin(event)
    {
        event.preventDefault();
        event.stopPropagation();

        var promise = new Promise(function(onSnLoginResolve, onSnLoginReject) {

            var sn = event.target.dataset.sn;

            if (sn === 'telegram') {

                telegramLoginBegin();

                return;
            }

            /*
                По клику кнопка открывает окно авторизации
                Запускается скрипт который ждет от окна данные:
                - Долго ждет - валится в ошибку
                - Окно закрыто - валится в ошибку
                - Если удалось получить из окна данные - получает
                    - Проверяет данные - если все ок, то считаем что пользователь верифицирован
                                       - если не ок - валится в ошибку
             */

            var snModalInterval; // setInterval handler
            var snModalIntarvalIterations = 0; // текущее количество опросов окна
            var snModalIntervalMaxIterations = 60; // максимальное количество опросов окна
            var snModalIterationMSec = 1000; // время задержки между опросами
            var snWindow; // окно

            snWindow =  window.open('https://www.sostav.ru/socialapi/authorize?social_id='+sn+'&redirect_uri=' + window.location.origin + '/vote/socialuser/auth', 'vote', 'width=800,height=600,resizable=no,scrollbars=no,status=no');
            w.voteShowModal('Ждем вашего разрешения...');

            snModalIntarvalIterations = 0;
            snModalInterval = setInterval(function(){

                snModalIntarvalIterations++;

                if (snModalIntarvalIterations > snModalIntervalMaxIterations) {

                    // истекло время ожидания

                    clearInterval(snModalInterval);
                    w.voteShowModal('Не дождались вашего разрешения. Время ожидания истекло ('+(snModalIntervalMaxIterations*snModalIterationMSec/1000)+'сек)');
                    snWindow.close();
                    snWindow = null;
                    onSnLoginReject();

                } else if (snWindow.closed) {

                    // окно было закрыто

                    clearInterval(snModalInterval);
                    w.voteShowModal('Не дождались вашего разрешения. Окно авторизации было закрыто.');
                    snWindow = null;
                    onSnLoginReject();

                } else {

                    // попытка получить ответ

                    var answerExists;

                    try {
                        answerExists = typeof snWindow.window.socialUserAuthResult;
                    } catch (e) {

                        //
                        // отсутствует необходимая функция в окне, которая вернет результат верификации
                        // это нормально, так как пользователь может ползать по открытому окну с соц сетью
                        // к которой нет доступа
                        // поэтому попытка найти нужную функцию в cross-origin окне может вызывать ошибку
                    }

                    if (answerExists === 'function') {

                        var authResult = snWindow.window.socialUserAuthResult();

                        clearInterval(snModalInterval);
                        snWindow.close();
                        snWindow = null;

                        if (authResult.ok) {
                            onSnLoginResolve(authResult);
                        } else {
                            w.voteShowModal(authResult.message);
                            onSnLoginReject();
                        }
                    }
                }

            }, snModalIterationMSec);

        });

        promise.then(function (res) {
            if (w.localStorage) {
                w.localStorage.setItem('snloginsuccess', '1');
            }
            location.reload();
        });

    }

    function createOneSnBtn(sn)
    {
        var btn = document.createElement('button');
        btn.type = 'button';
        btn.innerText = 'Пройти верификацию';
        btn.classList.add('app-btn', 'app-btn--icon');
        btn.setAttribute('data-sn', sn);
        btn.addEventListener('click', onSnLogin);

        return btn;
    }

    function createInitSnBtns(targetBtn)
    {
        var div = document.createElement('div');
        div.classList.add('vote-sns-list-selector');

        var sns = targetBtn.closest('.js-vote-buttons').dataset.sns.split(';');
        sns.forEach(function(sn) {
            div.appendChild(createOneSnBtn(sn))
        })

        return div;
    }

    function initSn(targetBtn)
    {
        return new Promise(function(resolve, reject) {

            var btns = createInitSnBtns(targetBtn);
            w.voteShowModal('Для голосования требуется верификация через соц. сеть. Кликните на выбранный значок ' +
                'аккаунта чтобы продолжить. Это необходимо, чтобы защитить участников от возможной накрутки. ' +
                'Мы используем ваш аккаунт только для голосования и сохраним только ваш идентификатор. Вы сможете ' +
                'отменить верификацию в любой момент.<br><br>', btns)

            // вернем результат - что проголосовать не получилось
            // silent - без какого-либо уведомления для пользователя
            resolve({
                ok: false,
                need: 'silent',
            })
        })
    }

    function needSnLogin(sn)
    {
        return new Promise(function(needSnLoginResolve, needSnLoginReject){

            // кнопка перехода в окно авторизации через соц сеть
            var btn = document.createElement('button');
            btn.type = 'button';
            btn.innerText = 'Пройти верификацию';
            btn.classList.add('app-btn');
            btn.addEventListener('click', function() {

                /*
                По клику кнопка открывает окно авторизации
                Запускается скрипт который ждет от окна данные:
                - Долго ждет - валится в ошибку
                - Окно закрыто - валится в ошибку
                - Если удалось получить из окна данные - получает
                    - Проверяет данные - если все ок, то считаем что пользователь верифицирован
                                       - если не ок - валится в ошибку
                 */

                var snModalInterval; // setInterval handler
                var snModalIntarvalIterations = 0; // текущее количество опросов окна
                var snModalIntervalMaxIterations = 60; // максимальное количество опросов окна
                var snModalIterationMSec = 1000; // время задержки между опросами
                var snWindow; // окно

                snWindow =  window.open('https://www.sostav.ru/socialapi/authorize?social_id='+sn+'&redirect_uri=' + window.location.origin + '/vote/socialuser/auth', 'vote', 'width=800,height=600,resizable=no,scrollbars=no,status=no');
                w.voteShowModal('Ждем вашего разрешения...');

                snModalIntarvalIterations = 0;
                snModalInterval = setInterval(function(){

                    snModalIntarvalIterations++;

                    if (snModalIntarvalIterations > snModalIntervalMaxIterations) {

                        // истекло время ожидания

                        clearInterval(snModalInterval);
                        w.voteShowModal('Не дождались вашего разрешения. Время ожидания истекло ('+(snModalIntervalMaxIterations*snModalIterationMSec/1000)+'сек)');
                        snWindow.close();
                        snWindow = null;
                        needSnLoginReject();

                    } else if (snWindow.closed) {

                        // окно было закрыто

                        clearInterval(snModalInterval);
                        w.voteShowModal('Не дождались вашего разрешения. Окно авторизации было закрыто.');
                        snWindow = null;
                        needSnLoginReject();

                    } else {

                        // попытка получить ответ

                        var answerExists;

                        try {
                            answerExists = typeof snWindow.window.socialUserAuthResult;
                        } catch (e) {

                            //
                            // отсутствует необходимая функция в окне, которая вернет результат верификации
                            // это нормально, так как пользователь может ползать по открытому окну с соц сетью
                            // к которой нет доступа
                            // поэтому попытка найти нужную функцию в cross-origin окне может вызывать ошибку
                        }

                        if (answerExists === 'function') {

                            var authResult = snWindow.window.socialUserAuthResult();

                            clearInterval(snModalInterval);
                            snWindow.close();
                            snWindow = null;

                            if (authResult.ok) {
                                //w.voteShowModal(authResult.message);
                                needSnLoginResolve();
                            } else {
                                w.voteShowModal(authResult.message);
                                needSnLoginReject();
                            }
                        }
                    }

                }, snModalIterationMSec);
            });

            w.voteShowModal('Чтобы проголосовать через этот аккаунт, нам необходимо ваше разрешение. Мы не собираем ваши данные и не храним информацию о вас.<br><br>', btn)

        });
    }

    function voteError(message)
    {
        w.voteShowModal(message || 'Не удалось проголосовать. Возникла ошибка.', null, 'error')
    }


    function voteBy_sn(catItemId, targetBtn)
    {
        var sn = targetBtn.dataset.sn;

        if (sn === 'init') {
            return initSn(targetBtn);
        }

        return new Promise(function(resolve, reject) {

            var FD = new FormData();
            FD.append('catItemId', catItemId);
            FD.append('sn', targetBtn.dataset.sn);
            FD.append('voice', targetBtn.dataset.voice);
            FD.append(
                document.querySelector('meta[name=csrf-param]').getAttribute('content'),
                document.querySelector('meta[name=csrf-token]').getAttribute('content'),
            );

            var xhr = fetch('/vote/voice/set', {
                method: 'post',
                body: FD
            }).then(function(res) {
                return res.json();
            }).then(function(json) {
                if (json.ok === false) {
                    if (json.need === 'sn-login') {

                        return initSn(targetBtn)
                    }
                }

                resolve(json);

            }).catch(function(err) {
                reject(err);
            })

        });
    }

    function createInitExpertBtns(targetBtn, containerId)
    {
        var catItemId = targetBtn.closest('.js-vote-buttons').getAttribute('data-cat_item_id');
        var FD = new FormData();
        FD.append('catItemId', catItemId);
        FD.append(
            document.querySelector('meta[name=csrf-param]').getAttribute('content'),
            document.querySelector('meta[name=csrf-token]').getAttribute('content'),
        );

        var xhr = fetch('/vote/voice/expert-available', {
            method: 'post',
            body: FD
        }).then(function(res) {
            return res.json();
        }).then(function(json) {

            if (json.ok === false) {

                if (json.need === 'remove-voice') {

                    var div = document.createElement('div');

                    var container = document.getElementById(containerId);
                    if (container) {
                        container.innerHTML = 'Вы уже проголосовали за эту работу.';
                        container.appendChild(div);
                    }
                }

                return;
            }

            var availableVoices = json.availableVoices;

            var div = document.createElement('div');
            div.classList.add('vote-expert-list-selector');

            var voices = ["3", "4", "5"];
            if (availableVoices.length) {
                for (var i = 0; i < voices.length; i++) {

                    var btn = document.createElement('button');
                    btn.classList.add('app-btn', 'app-btn--outline', 'js-voice-btn', 'vote-star-btn', 'vote-star-btn--' + voices[i]);

                    if (availableVoices.indexOf(voices[i]) === -1) {
                        btn.classList.add('vote-star-btn--disabled');
                    } else {
                        btn.setAttribute('data-voice', voices[i]);
                        btn.addEventListener('click', function (event) {
                            event.preventDefault()
                            event.stopPropagation()
                            vote('experts', catItemId, this);
                        });
                    }

                    btn.innerHTML = '<span class="vote-star-btn__icon vote-star-btn__icon--' + voices[i] + '"></span>';

                    div.appendChild(btn)
                }
            } else {
                div.innerHTML = 'Вы потратили все свои голоса. Если хотите переголосовать, сначала удалите голос у другой работы.';
            }

            var container = document.getElementById(containerId);
            if (container) {
                container.innerHTML = '';
                container.appendChild(div);
            }

        }).catch(function(err) {
            reject(err);
        })
    }

    function initExpert(targetBtn)
    {
        return new Promise(function(resolve, reject) {

            var containerId = 'expert-voice-buttons-container';
            var div = document.createElement('div')
            div.id = containerId;
            div.innerHTML = 'Загружаем доступные оценки';

            w.voteShowModal('Какую оценку вы хотите поставить этому комиксу?<br><br>', div)

            createInitExpertBtns(targetBtn, containerId);

            // вернем результат - что проголосовать не получилось
            // silent - без какого-либо уведомления для пользователя
            resolve({
                ok: false,
                need: 'silent',
            })
        })

    }

    function voteBy_experts(catItemId, targetBtn)
    {
        var voice = targetBtn.dataset.voice;

        if (!voice) {
            return initExpert(targetBtn)
        }

        return new Promise(function(resolve, reject) {

            var FD = new FormData();
            FD.append('catItemId', catItemId);
            FD.append('voice', targetBtn.dataset.voice);
            FD.append(
                document.querySelector('meta[name=csrf-param]').getAttribute('content'),
                document.querySelector('meta[name=csrf-token]').getAttribute('content'),
            );

            var xhr = fetch('/vote/voice/set', {
                method: 'post',
                body: FD
            }).then(function(res) {
                return res.json();
            }).then(function(json) {
                if (json.ok === false) {
                    reject({
                        ok: false,
                        message: json.message
                    })
                }

                flipExpertVoicePlace(catItemId, 'vote', targetBtn.dataset.voice);

                resolve(json);

            }).catch(function(err) {
                reject(err);
            })

        });
    }

    function vote(voiceType, catItemId, targetBtn)
    {
        targetBtn.classList.add('process-voice');

        var votePromise;

        switch (voiceType) {
            case 'sn':
                votePromise = voteBy_sn(catItemId, targetBtn);
                break;
            case 'experts':
                votePromise = voteBy_experts(catItemId, targetBtn);
                break;
            default:
                voteError('Неизвестный метод голосования');
                break;
        }

        if (!votePromise) {
            return;
        }

        votePromise.then(function(res){

            if (res.ok === false) {

                if (res.need === 'silent') {
                    return;
                }

                w.voteShowModal(res.message, false, 'error');

            } else if (res.ok) {

                var counterEls = document.querySelectorAll('.js-voice-counter-' + catItemId);
                if (counterEls.length) {
                    for (var i = 0; i < counterEls.length; i++) {
                        counterEls[i].innerHTML = res.data.counts.voicesCount;
                    }
                }
                var counterWordEls = document.querySelectorAll('.js-voice-counter-word-' + catItemId);
                if(counterWordEls.length) {
                    for (var i = 0; i < counterWordEls.length; i++) {
                        counterWordEls[i].innerHTML = res.data.counts.voicesCountWord;
                    }
                }
                var sumEls = document.querySelectorAll('.js-voice-sum-' + catItemId);
                if (sumEls.length) {
                    for (var i = 0; i < sumEls.length; i++) {
                        sumEls[i].innerHTML = res.data.counts.voicesSum;
                    }
                }
                var sumWordEls = document.querySelectorAll('.js-voice-sum-word-' + catItemId)
                if (sumWordEls.length) {
                    for (var i = 0; i < sumWordEls.length; i++) {
                        sumWordEls[i].innerHTML = res.data.counts.voicesSumWord;
                    }
                }
                var voicePlaces = document.querySelectorAll('.js-voice-place-' + catItemId);
                if (voicePlaces) {
                    for (var i = 0; i < voicePlaces.length; i++) {
                        voicePlaces[i].classList.add('voted');
                    }
                }

                w.voteShowModal(res.message, false, 'success');
            } else {

                if (res.message) {
                    w.voteShowModal(res.message, false, 'error');
                } else {
                    w.voteShowModal('Не удалось проголосовать из-за неизвестной ошибки', false, 'error');
                }

            }
        });

        votePromise.catch(function(e){
            voteError('не удалось проголосовать из за ошибки: ' + e.message)
        });

        votePromise.finally(() => {
            setTimeout(function(){
                targetBtn.classList.remove('process-voice');
            }, 1000)
        });
    }

    function flipExpertVoicePlace(catItemId, type, voice)
    {
        var placeEls = document.querySelectorAll('.js-expert-voice-place-' + catItemId);

        for (var i = 0; i < placeEls.length; i++) {

            var placeUnvote = placeEls[i].querySelector('.js-expert-voice-place-voices');
            if (placeUnvote) {

                if (voice) {
                    var unvoteIconsEl = placeUnvote.querySelector('.vote-star-btn__icon');
                    if (unvoteIconsEl) {
                        unvoteIconsEl.classList.remove('vote-star-btn__icon--3', 'vote-star-btn__icon--4', 'vote-star-btn__icon--5');
                        unvoteIconsEl.classList.add('vote-star-btn__icon--' + voice);
                    }
                }

                if (type === 'vote') {
                    placeUnvote.classList.remove('hidden')
                } else {
                    placeUnvote.classList.add('hidden')
                }
            }

            var placeVote = placeEls[i].querySelector('.js-expert-voice-place-buttons');
            if (placeVote) {
                if (type === 'vote') {
                    placeVote.classList.add('hidden')
                } else {
                    placeVote.classList.remove('hidden')
                }
            }
        }
    }

    function removeExpertVoice(catItemId, targetBtn)
    {
        return new Promise(function(resolve, reject) {

            var FD = new FormData();
            FD.append('catItemId', catItemId);
            FD.append(
                document.querySelector('meta[name=csrf-param]').getAttribute('content'),
                document.querySelector('meta[name=csrf-token]').getAttribute('content'),
            );

            fetch('/vote/voice/remove', {
                method: 'post',
                body: FD
            }).then(function(res) {
                return res.json();
            }).then(function(json) {

                if (json.ok) {

                    flipExpertVoicePlace(catItemId, 'unvote');
                    resolve(json);
                } else {
                    reject({
                        ok: false,
                        message: json.message
                    })
                }

            }).catch(function(err) {
                reject(err);
            })

        })

    }

    function onVote(event)
    {
        if (event.target.classList.contains('js-unvoice-btn')) {
            event.preventDefault();
            removeExpertVoice(event.target.closest('.js-vote-buttons').dataset.cat_item_id, event.target)
            return;
        } else if (event.target.classList.contains('js-items-results-button')) {
            event.preventDefault();
            var link = event.target.closest('.vote-items-page-card');
            if (link) {
                location.href = link.href + '#results'
            }
            return;
        } else if (!event.target.classList.contains('js-voice-btn')) {
            return;
        }

        event.preventDefault();

        if (event.target.classList.contains('process-voice')) {
            w.voteShowModal('Пожалуйста дождитесь завершения процесса голосования...');
            return;
        }

        var buttonsContainer = event.target.closest('.js-vote-buttons');
        var catItemId = buttonsContainer.dataset.cat_item_id || '';
        var voiceType = buttonsContainer.dataset.voice_type || '';

        vote(voiceType, catItemId, event.target);
    }

    function init(buttonsContainers)
    {
        for (var i = 0; i < buttonsContainers.length; i++) {
            buttonsContainers[i].addEventListener('click', onVote, false);
        }

        if (buttonsContainers[0].dataset.voice_type === 'sn' && w.localStorage) {
            var snLoginSuccess = w.localStorage.getItem('snloginsuccess');
            w.localStorage.removeItem('snloginsuccess');
            if (snLoginSuccess === '1') {
                w.voteShowModal('Теперь вы можете проголосовать с помощью выбранного аккаунта');
            }
        }
    }

    w.aicomics_voter = {
        init: init,
        vote: vote,
    }

})(window, document);