var LiveEvents = (function() {
    var pusher = null;
    var _liveEvents = function(options) {
        var _this = this;
        this.options = $.extend({
            liveEventId: null,
            websocketAppKey: null,
            updateEntriesContainer: "#live-events-entries-select-locale",
            entriesContainer: "#live-event-entries",
            formContainer: "#live-event-comment-form",
            submitSelector: '[data-action="submit"]',
            translatorSelector: '[data-action="translate"]',
            localeSelector: '#cms_live_event_comment_locale_locale',
            clearFormSelector: '[data-action="clear-form"]',
            scoreboardFormSelector: "#cms_live_event_scoreboard",
            scoreboardSubmit: '#cms_live_event_scoreboard_modal button[data-btn-type="save"]',
            scoreboardModalSelector: "#cms_live_event_scoreboard_modal",
            timeTextSelector: '[data-time-text]',
            dateTimeTextSelector: '.form_datetime',
            formatSelector: '[data-format]',
            locale: null,
            _locale: null,
            liveEvent: null,
            formSelector: '[name="cms_live_event_comment_locale"]',
            refreshButtonId: "#refresh-entries",
            editorConfig: {
                toolbar: "liveEvent"
            },
            user: null
        }, options);

        this.translator = new CsTranslator();
        this.ckEditorHelper = new CKEditorHelper();
        this.locale  = this.options.locale;
        this._locale = this.options._locale;
        this.liveEvent = this.options.liveEventId;
        this.websocketAppKey = this.options.websocketAppKey;
        this.websocketPusher = this.options.websocketAppKey && typeof ComitiumLiveEventPusher !== 'undefined' ?
          ComitiumLiveEventPusher.init(
            this.websocketAppKey,
            this.liveEvent,
            {
                onPresenceSync: function(data){
                    _this.wsOnPresenceSync(data)
                },
                onCreate: function(data){
                    _this.wsCreated(data);
                },
                onUpdate: function(data) {
                    _this.wsUpdated(data);
                },
                onDelete: function(data){
                    _this.wsDeleted(data);
                },
                onScoreboardUpdate: function(data){
                    _this.wsOnScoreboardUpdated(data);
                }
            }
          ) :
          null;
        this.usersCounter = 0;
        this.lastCounter = 0;

        this.bindEvents();
    };

    _liveEvents.prototype.bindEvents = function() {
        var _this = this;

        /*
        * Assigned to right top panel locale buttons (appears when less than "x" locales are loaded)
        * Refer to CmsBundle:LiveEvents:index.html.twig
        */
        $(this.options.updateEntriesContainer).find("[data-locale]").on("click", function(e){
            _this.updateEntries($(this).data("locale"));
        });

        /*
         * Assigned to refresh button. Send ajax call with current locale selected
         * Refer to CmsBundle:LiveEvents:index.html.twig
         */
        $(this.options.refreshButtonId).on("click", function(e){
            e.preventDefault();
            _this.updateEntries(_this.locale);
        });

        /*
         * Assigned to right top panel select input (appears when more than "x" locales are loaded)
         * Refer to CmsBundle:LiveEvents:index.html.twig
         */
        $(this.options.updateEntriesContainer).find("select").on("change", function(e){
            _this.updateEntries($(this).val());
        });

        /*
         * Assigned to right top panel select input (appears when more than "x" locales are loaded)
         * Refer to CmsBundle:LiveEvents:index.html.twig
         */
        $(this.options.submitSelector).find("a").on("click", function(e){
            e.preventDefault();
            _this.submitForm($(this).data("locale"));
        });

        /*
         * Assigned to init translations
         * Refer to CmsBundle:LiveEvents:index.html.twig
         */
        $(this.options.translatorSelector).find("a").on("click", function(e){
            e.preventDefault();
            _this.initTranslation($(this).data("locale-code"));
        });

        $(this.options.clearFormSelector).on("click", function(e){
            e.preventDefault();
            _this.clearForm();
        });

        $(this.options.scoreboardSubmit).on("click", function(e){
            e.preventDefault();
            _this.submitScoreboard();
        });

        $('[data-action="reset-time"]').on("click", function(e){
            e.preventDefault();
            var target = $($(this).data("for"));
            var date = new Date();
            target.timepicker("setTime", moment(date).format('HH:mm'));
        });

        _this.bindRecallEvents();

        if (this.websocketPusher !== null) {
            var equalCounter = 0;

            setInterval(function(){
                if (_this.lastCounter === _this.usersCounter) {
                    equalCounter++;

                    if (equalCounter >= 6) {
                        var element = $("[data-live-events-people]");
                        equalCounter = 0;
                        element.removeClass("trending-up trending-down")
                    }
                }

                _this.lastCounter = _this.usersCounter
            }, 10000);

        } else {
            /**
             * Update scoreboard if other users have had made updates with ping metodoloy
             */
            $('#cms_live_event_scoreboard_modal').on('show.bs.modal', function (e) {
                _this.updateScoreboard();
            });
        }
    };

    _liveEvents.prototype.wsOnPresenceSync = function(presence) {
        this.usersCounter = Object.keys(presence.state).length;

        $('#websocket-counter').text(this.usersCounter);

        if (this.lastCounter > 0) {
            var element    = $("[data-live-events-people]");
            var oscilation = (this.lastCounter*20/100);
            var rate       = this.lastCounter - this.usersCounter;
            var rateAbs    = Math.abs(rate);

            if (rate < 0 && rateAbs >= oscilation) {
                equalCounter = 0;
                element
                  .removeClass("trending-down trending-up")
                  .addClass("trending-up");
            } else if (rate > 0 && rateAbs >= oscilation) {
                equalCounter = 0;
                element
                  .removeClass("trending-down trending-up")
                  .addClass("trending-down");
            }
        }
    }
    _liveEvents.prototype.wsOnScoreboardUpdated = function(resp){
        $("#cms_live_event_scoreboard_homeTeam").val(resp.homeTeam);
        $("#cms_live_event_scoreboard_awayTeam").val(resp.awayTeam);
        $("#cms_live_event_scoreboard_homeValue").val(resp.homeValue);
        $("#cms_live_event_scoreboard_awayValue").val(resp.awayValue);

        $("#cms_live_event_scoreboard_freeText")
          .val(resp.freeText)
          .trigger("change");

        var startDate = resp.startDate ? moment(resp.startDate).format("H:mm") : '',
          endDate   = resp.endDate ? moment(resp.endDate).format("H:mm") : '';
        $("#cms_live_event_scoreboard_startDate").val(startDate);
        $("#cms_live_event_scoreboard_endDate").val(endDate);

        if (this.shouldDisplayScoreboardWebsocketNotification(resp)) {
            showToastrNotification('info', Translator.trans('live_event.entries.ws.scoreboard_update', {'user': resp.user}));
        }
    }
    _liveEvents.prototype.wsCreated = function(resp){
        if (this.shouldDisplayWebsocketNotification(resp)) {
            showToastrNotification('info', Translator.trans('live_event.entries.ws.created', {'user': resp.user }));
            this.updateEntries(this.locale);
        }
    }
    _liveEvents.prototype.wsUpdated = function(resp) {
        if (this.shouldDisplayWebsocketNotification(resp)) {
            showToastrNotification('info', Translator.trans('live_event.entries.ws.updated', {'user': resp.user}));
            this.updateEntries(this.locale);
        }
    }

    _liveEvents.prototype.wsDeleted = function(resp){
        if (this.shouldDisplayWebsocketNotification(resp)) {
            showToastrNotification('info', Translator.trans('live_event.entries.ws.deleted', {'user': resp.user}));
            this.updateEntries(this.locale);
        }
    }

    _liveEvents.prototype.bindRecallEvents = function() {

        var _this = this;

        $(this.options.entriesContainer).find('[data-action="live-entry-delete"]').on("click", function(e){
            e.preventDefault();
            _this.removeEntries($(this));
        });

        $(this.options.entriesContainer).find('[data-action="live-entry-edit"]').on("click", function(e){
            e.preventDefault();
            _this.updateForm($(this));
        });


        $(this.options.formContainer).find(".form_datetime").each( function(){
            $(this).on("change", function(){
                var inputDate = moment($(this).val(),"DD/MM/YYYY - HH:II");

                if (inputDate < moment()) {
                    $(this).val(moment().format("DD/MM/YYYY - HH:mm"));
                }
            });
        });

        $(this.options.formContainer).find('[data-toggle="popover"]').popover();

        this.bindResetDateTime();
        this.bindMirrorFields();
    };

    _liveEvents.prototype.bindResetDateTime = function() {
        $('[data-action="reset-datetime"]').on("click", function(e){
            e.preventDefault();
            $($(this).data("for")).val("");
        });
    };

    _liveEvents.prototype.bindMirrorFields = function(){

        var _this = this;

        $(this.options.formatSelector).on("change",function(){
            var value = $(this).select2("data");
            $(_this.options.formatSelector).select2("data", value);
        });

        $(this.options.timeTextSelector).on("change",function(){
            var value = $(this).val();
            $(_this.options.timeTextSelector).val(value);
        });

        $(this.options.dateTimeTextSelector).on("change",function(){
            var value = $(this).val();
            $(_this.options.dateTimeTextSelector).val(value);
        });
    };

    _liveEvents.prototype.checkNotEmptyData = function(locale) {

        var form = $(this.options.formSelector);
        var success = true;
        var _locale = locale;

        form.find(".cs-live-events-entry-item").each(function() {

            var locale = $(this).data("locale");
            var title  = $(this).find('[id$="_title"]').val();
            var description  = $(this).find('[id$="_description"]').val();

            if (typeof _locale !== "undefined") {
                if (locale == _locale) {
                    if ($.trim(title) === "" && $.trim(description) === "") {
                        success = false;
                    }
                }
            } else {
                if ($.trim(title) === "" && $.trim(description) === "") {
                    success = false;
                }
            }
        });

        return success;
    };

    _liveEvents.prototype.submitForm = function(locale) {

        var _this = this;
        var form  = $(this.options.formSelector);
        var _locale = this.locale;

        if (locale) {
            _locale = locale;
        }

        $(this.options.localeSelector).val(locale);

        if (this.checkNotEmptyData(locale) === false) {
            showToastrNotification('error', Translator.trans('live_event.form.messages.empty_data'));
            return false;
        }


        $.ajax({
            url: form.attr("action"),
            data: form.serialize(),
            method: form.attr("method"),
            dataType: "json",
            beforeSend: function(){
                $('.cs-module-spinner').show();
            },
            complete: function(){
                $('.cs-module-spinner').hide();
            },
            success: function(response) {

                showToastrNotification('success', Translator.trans('live_event.form.messages.success'));

                if (!locale) {
                    _this.clearForm();
                }

                _this.updateEntries(_locale);
                _this.setActiveLocale(_locale);

                _this.sendToWebSocket(response.data, response.action, response.user);
            },
            error: function(response) {
                var errors = $.parseJSON(response.responseText);
                form.find('.form-group').removeClass("has-error");
                $.each(errors, function(k,v){
                    form.find('[data-locale="'+k+'"]').find('label[for$="_description"]').parent().addClass("has-error")
                });
                showToastrNotification('error', Translator.trans('live_event.form.messages.error'));
            }
        })
    };

    _liveEvents.prototype.updateEntries = function(locale) {
        var _this = this;

        _this.locale = locale;

        $.ajax({
            url: Routing.generate("cs_cms_live_events_entries_show_entries", { id:this.liveEvent, localeId:locale, _locale:_this._locale }),
            method: "get",
            dataType: "html",
            beforeSend: function() {
                $(_this.options.entriesContainer).css("opacity", "0.2");
            },
            complete: function() {
                $(_this.options.entriesContainer).css("opacity", "1");
                _this.bindRecallEvents();
            },
            success: function(response) {
                $(_this.options.entriesContainer).replaceWith(response);
            }
        });
    };

    _liveEvents.prototype.updateForm = function(el) {
        var _this = this;
        var _parent = el ? el.parents("[data-id]"): null;
        var id = _parent ? _parent.data("id") : 0;

        $.ajax({
            url: Routing.generate("cs_cms_live_events_entries_form", { id: id, liveEvent: _this.liveEvent, _locale:_this._locale }),
            method: "get",
            dataType: "html",
            beforeSend: function() {
                $(_this.options.formContainer).css("opacity", "0.2");
            },
            complete: function() {
                $(_this.options.formContainer).css("opacity", "1");
                SpellText.bindFunctions();
                _this.bindMirrorFields();
            },
            success: function(response) {
                $(_this.options.formContainer).replaceWith(response);
                _this.refreshForm();
            }
        });
    };

    _liveEvents.prototype.setActiveLocale = function(locale) {

        $(this.options.updateEntriesContainer)
            .find("label")
            .removeClass("active")
            .end()
            .find('[data-locale="'+locale+'"]')
            .addClass("active")
        ;

        $(this.options.updateEntriesContainer).find("select").val(locale);
        $(this.options.updateEntriesContainer).find("select").trigger("change");
    };

    _liveEvents.prototype.refreshForm = function() {
        var _this = this;

        $(this.options.formContainer).find("textarea").each( function(){
            _this.ckEditorHelper.loadEditor($(this).attr("id"), _this.options.editorConfig);
        });

        ComponentsPickers.init();

        $(this.options.formContainer).find('[data-toggle="popover"]').popover();

        _this.bindResetDateTime();

        $(this.options.formContainer).find("select").each( function(){
            $(this).select2();
        });
    };

    _liveEvents.prototype.clearForm = function() {
        this.updateForm();
    };

    _liveEvents.prototype.removeEntries = function(el) {

        var _this = this;
        var _parent = el.parents("[data-id]");
        var _modal = window.bootstrap.createModal().show(
            Translator.trans('live_event.entries.modal.delete.title'),
            Translator.trans('live_event.entries.modal.delete.message'),
            Translator.trans('live_event.entries.modal.delete.submit')
        );

        _modal.find('[data-btn-type="save"]').on('click', function (e) {

            var _self = $(this);

            $.ajax({
                url: Routing.generate("cs_cms_live_events_entries_delete", {id: _parent.data("id")}),
                dataType: "json",
                method: "post",
                beforeSend: function() {
                    _self.addClass("disabled");
                },
                success: function(response) {
                    _parent.fadeOut(function(){
                        showToastrNotification('success', Translator.trans('live_event.entries.messages.success.delete'));
                    });

                    _this.sendToWebSocket(response.data, response.action, response.user);

                },
                complete: function() {
                    _modal.find('[data-dismiss="modal"]').trigger('click');
                    _modal.remove();
                    _this.clearForm();
                }
            });
        });
    };

    _liveEvents.prototype.initTranslation = function(locale) {

        var form   = $(this.options.formSelector);
        var fields = [];
        var _this  = this;


        form.find(".cs-live-events-entry-item").each(function(){

            var locale = $(this).data("locale-code");
            var title  = $(this).find('[id$="_title"]').val();
            var titleId  = $(this).find('[id$="_title"]').attr("id");
            var description  = $(this).find('[id$="_description"]').val();
            var descriptionId  = $(this).find('[id$="_description"]').attr("id");

            fields.push({ locale: locale, title: {id:titleId, value:title} , description: {id:descriptionId, value:description}});
        });

        var data = this.buildTranslateData(fields, locale);

        if (data.length > 0) {
            $('.cs-module-spinner').show();
        };

        $.each(data, function(k,v){
            _this.translator.initTranslation(v,
                function(response){
                    $.each(response,function(k,v){

                        var node = $("#"+ k);
                        var nodeId = node.attr('id');
                        var isCKEditor = CKEDITOR.instances[nodeId];
                        var outputState = checkOutputFormat(v, isCKEditor);

                        if (outputState.errors === true) {
                            displaySpellCheckerErrors(node);
                        }

                        if (isCKEditor) {
                            CKEDITOR.instances[nodeId].setData(outputState.value);
                        }

                        node.val(outputState.value);
                    });

                    $('.cs-module-spinner').hide();
                },
                function(response, error, jqXHR){
                    // Show error if is needed here
                    $('.cs-module-spinner').hide();
                });
        });
    };

    _liveEvents.prototype.buildTranslateData = function(fields, locale) {
        var countFields = fields.length;
        var originLang  = null;
        var counter = 0;
        var toTranslate = [];
        var localeIsFilled = false;
        var data = [];
        var _this = this;

        $.each(fields, function(k,v){
            if (v) {

                if ($.trim(v.description.value) != "" || $.trim(v.title.value) != "") {
                    if (originLang === null) {
                        originLang = this;
                    }

                    counter++;

                    if (locale == v.locale) {
                        localeIsFilled = true;
                    }

                } else {
                    toTranslate.push(this);
                }
            }

        });

        if (counter == countFields) {
            showToastrNotification('error', Translator.trans('live_event.form.messages.translate.error.full'));
        } else if (originLang === null) {
            showToastrNotification('error', Translator.trans('live_event.form.messages.translate.error.empty'));
        }else if (localeIsFilled == true) {
            showToastrNotification('error', Translator.trans('live_event.form.messages.translate.error.sameLocale'));
        } else {
            $.each(toTranslate, function(k,v){
                if (!locale ) {
                    data.push({
                        localeSource: originLang.locale,
                        localeDestination: v.locale,
                        data: _this.parseData(v,originLang)
                    });
                } else {

                    if (v.locale === locale) {
                        data.push({
                            localeSource: originLang.locale,
                            localeDestination: v.locale,
                            data: _this.parseData(v,originLang)
                        });
                    }
                }
            });
        }

        return data;
    };

    _liveEvents.prototype.updateScoreboard = function(el) {
        var form = $(this.options.scoreboardFormSelector);
        var id = form.attr("action").match(/\d+/);
        var homeNode = $('#cms_live_event_scoreboard_homeValue');
        var awayNode = $('#cms_live_event_scoreboard_awayValue');

        $.ajax({
            url: Routing.generate("cs_cms_live_events_scoreboard_get", {id:id}),
            method: "post",
            dataType: "json",
            complete: function() {
                homeNode.val();
                awayNode.val();
            },
            success: function(response) {
                homeNode.val(response.homeValue);
                awayNode.val(response.awayValue);
            }
        });
    }

    _liveEvents.prototype.submitScoreboard = function(el) {
        var _this = this;
        var form = $(_this.options.scoreboardFormSelector);

        if (form.valid()) {
            $.ajax({
                url: form.attr("action"),
                method: form.attr("method"),
                data: form.serialize(),
                beforeSend: function(){
                    $(_this.options.scoreboardModalSelector).modal('hide');
                    $('.cs-module-spinner').show();
                },
                complete: function(){
                    $('.cs-module-spinner').hide();
                },
                success: function(response) {
                    showToastrNotification('success', Translator.trans('live_event.entries.scoreboard.messages.success'));
                    _this.sendToWebSocket(response.data, response.action, response.user);
                },
                error: function(){
                    showToastrNotification('error', Translator.trans('live_event.entries.scoreboard.messages.error'));
                }
            });
        } else {
            showToastrNotification('error', Translator.trans('live_event.entries.scoreboard.messages.form_error'));
        }
    };

    _liveEvents.prototype.parseData = function(data, originLang) {
        var dataParsed = {};

        if (originLang.title.value != "") {
            dataParsed[data.title.id] = originLang.title.value;
        }

        if (originLang.description.value != "") {
            dataParsed[data.description.id] = originLang.description.value;
        }

        return dataParsed;
    };

    _liveEvents.prototype.sendToWebSocket = function(data, action, user) {
        if (!this.websocketAppKey) {
            return;
        }

        var length = data.length ? data.length : 0;

        if (length > 0) {
            for (x=0; x < length; x++) {
                this._sendToWebSocket(data[x], action, user);
            }
        } else {
            this._sendToWebSocket(data, action, user);
        }
    }

    _liveEvents.prototype._sendToWebSocket = function(data, action, user) {
        if (this.websocketPusher === null) {
            return;
        }

        var data = Object.assign(data, {user: user});

        switch (action) {
            case "create":
                this.websocketPusher.create(data);
                break;
            case "update":
                this.websocketPusher.update(data);
                break;
            case "delete":
                this.websocketPusher.delete(data);
                break;
            case "scoreboard":
                this.websocketPusher.scoreboardUpdate(data);
                break;
        }
    }

    _liveEvents.prototype.shouldDisplayWebsocketNotification = function (resp) {
        return this.options._locale === resp.locale && this.options.user !== resp.user;
    }

    _liveEvents.prototype.shouldDisplayScoreboardWebsocketNotification = function (resp) {
        return this.options.user !== resp.user;
    }

    var checkOutputFormat = function(value, isCkEditor) {

        var status = {
            errors: false,
            value : value
        };

        if (isCkEditor) {
            return status;
        }

        if (value.match(/(.+)?<font color="#(([0-9a-fA-F]{2}){3}|([0-9a-fA-F]){3})">.+\<\/font\>(.+)?/)) {
            status.errors = true;

            value = value.replace(/<font color="#(([0-9a-fA-F]{2}){3}|([0-9a-fA-F]){3})">/gi, "");
            value = value.replace(/\<\/font\>/gi, "");

            status.value = value;
        }

        if (value.match(/(.+)?<span style="color:(green|red|yellow)">.+\<\/span\>(.+)?/)) {
            status.errors = true;

            value = value.replace(/<span style="color:(green|red|yellow)">/gi, "");
            value = value.replace(/\<\/span\>/gi, "");

            status.value = value;
        }

        return status;
    };

    var displaySpellCheckerErrors = function(node) {
        var spellCheckNode = node.parents('[data-action="spell_text"]');

        if (spellCheckNode) {
            SpellText.displayResult(spellCheckNode, "error");
        }
    };

    return {
        init: function(options) {
            return new _liveEvents(options);
        }
    };
})();
