define([
  // Application variable, always include it to have access to app methods.
  "app",

  //templates-loader: this loads templates async.
  "js/templates-loader",

  "modules/modal",

  "moment",
], function (app, T, modal, moment) {

    var DelayInformationModal = {
        Models: {}, Views: {}, Collections: {}
    };

    DelayInformationModal.Models.DelayInformationModal = Backbone.Model.extend({
        defaults: {
            batchNumber: null,
            delayId: null,
            parentId: null,
            line: null,
            productionItem: null,
            start: null,
            end: null,
            duration: null,
            delayCodeId: null,
            comments: null,
            delayCodes: null,
            sortDelayCodesByFrequency: null,
        },

        initialize: function () {
            this.options = {
                fetched: false,
            };

            this.set('sortDelayCodesByFrequency', (localStorage.getItem("delay-information-modal-sortDelayCodesByFrequency") == 'true'));
        },
        fetch: function (delayId) {
            var that = this;
            var QP = new Core.Database.QueryParameters();
            QP.Add("DelayID", "INT", delayId);
            QP.Add("Timezone", "VARCHAR", app.models.user.get("timezoneCode"));

            Core.Json.CallProcedure(app.DatabaseNames.OEE + ".WebApp.GetDelayData", QP, {
                onSuccess: function (data) {
                    if (data && data.Table && data.Table.length > 0) {
                        var delayCodes = data.Table1;

                        var delayCodeItems = {};
                        for (var i = 0; i < delayCodes.length; i++) {
                            var item = {
                                description: delayCodes[i].Description,
                                delayCodeId: delayCodes[i].DelayCodeID,
                                parentId: delayCodes[i].ParentID,
                                frequency: delayCodes[i].Frequency,
                                color: delayCodes[i].Color,
                                categoryName: delayCodes[i].CategoryName, 
                                children: null,
                            }

                            if (item.parentId) {
                                if (!delayCodeItems[item.parentId].children) delayCodeItems[item.parentId].children = {};
                                delayCodeItems[item.parentId].children[item.delayCodeId] = item;
                            }
                            else delayCodeItems[item.delayCodeId] = item;
                        }

                        that.set("delayCodes", delayCodeItems, { silent: true });

                        data = data.Table[0];

                        var values = _.extend({}, that.attributes, {
                            //Set as zero value in case that batch number is null.
                            //This is to handle differente cases depending if the delay
                            //has batch number or not depending on the screen where this modal is used.
                            //Set it as zero instead of let is a null to ask for zero value on template with
                            //handlebars helpers to display or not the fields of batch number.
                            batchNumber: (data.BatchNumber != null)
                                            ? data.BatchNumber
                                            : 0,
                            delayId: data.DelayId,
                            parentId: data.ParentId,
                            line: data.Line,
                            productionItem: data.ProductionItem,
                            start: data.Start,
                            end: data.End,
                            duration: data.Duration,
                            delayCodeId: data.DelayCodeID,
                            comments: data.Comments,
                        });

                        that.options.fetched = true;
                        that.set(values);
                    }
                },
                Secured: true,
            }, app.ConnectionStrings.app);
        },
    });

    DelayInformationModal.Views.DelayInformationModal = Backbone.View.extend({
        template: "delay-information-modal"
        , id: "delay-information-modal"
        , title: ""
        , className: "modal hide fade modal-wider"
        //default not cacheable, change this if you want the view to be cacheable
        // if the view is set as cacheable should also have a refresh method to reset the view without erasing the DOM.
        , isCacheable: true
        , initialize: function () {

            this.options.MYREFERENCES = {
                autoRefresh: {
                    enabled: true
                    , toid: null
                },
                rowData: null,
            };

            if (this.options.viewParams) {
                this.options.MYREFERENCES.rowData = this.options.viewParams.rowData;
            }

            this.options.currentPage = 0;
            this.options.totalPages = 0;

            this.options._isRendering = false;
            this.options._isRendered = false;

            this.model = new DelayInformationModal.Models.DelayInformationModal();

            this.bindEvents();
            _.bindAll(this);
        },
        events: {
            'click .close': function (event) {
                event.preventDefault();

                this.trigger('cancel');

                if (this.options.content && this.options.content.trigger) {
                    this.options.content.trigger('cancel', this);
                }
            }
            , 'click .btn-close': function (event) {
                event.preventDefault();

                this.trigger('cancel');

                if (this.options.content && this.options.content.trigger) {
                    this.options.content.trigger('cancel', this);
                }
            }
            , "click .btn-cancel": function (event) {
                event.preventDefault();

                this.trigger('cancel');

                if (this.options.content && this.options.content.trigger) {
                    this.options.content.trigger('cancel', this);
                }
            }
            , "click .btn-save": function (event) {
                event.preventDefault();
                this.save();
            }
            , "click .btn-arrow-left": function () {
                this.movePage('LEFT');
            }
            , "click .btn-arrow-right": function () {
                this.movePage('RIGHT');
            }
            , "click .btn-delay-code": "delayCodeBtn_clicked"
            , "change .sortDelayCodesByFrequency-checkbox": "sortDelayCodesByFrequencyCheckbox_changed"
        },

        render: function (container) {
            var that = this;
            var thatContainer = container;

            //the screens have a custompath, so it has to be specified in the customPath variable that is
            //then sent to the template loader.
            var customPath = app.oeeModule.screensPath + "delays/delay-information-modal/";

            if (this.model.get("delayId")) {
                T.render.call(this, this.template, function (tmp) {
                    if (!that.options.i18n) that.options.i18n = {};
                    app.getI18NJed(that, that.template, function (i18nJED) {
                        //storing internationalization data
                        that.options.i18n[that.template] = i18nJED;

                        var delayCodesSelect = [];
                        (function _parseDelayCodesOptions(dict, values, description) {
                            for (var i in dict) {
                                var t = dict[i];
                                if (t.children != null) {
                                    _parseDelayCodesOptions(t.children, values
                                        , (description != null) ? description + ' > ' + t.description : t.description
                                    );
                                } else {
                                    values.push({
                                        value: t.delayCodeId,
                                        label: (description != null) ? description + ' > ' + t.description : t.description,
                                        frequency: t.frequency,
                                        color: t.color,
                                        categoryName: t.categoryName, 
                                    });
                                }
                            }
                        })(that.model.get("delayCodes"), delayCodesSelect, null);

                        var ipp = 16; //itemsPerPage
                        var ipr = 4; //itemsPerRow
                        var pages = [];

                        //sorting delay codes alphabetically
                        delayCodesSelect = _.sortBy(delayCodesSelect, 'label');
                        //delayCodesSelect.reverse();

                        if (that.model.get('sortDelayCodesByFrequency') == true) {
                            delayCodesSelect = _.sortBy(delayCodesSelect, 'frequency', false);
                            delayCodesSelect.reverse();
                        }

                        _.each(delayCodesSelect, function (obj, inx) {
                            var page = Math.floor(inx / ipp);
                            var pageo;
                            if (!(pageo = pages[page])) {
                                pageo = { pageNum: page, rows: [] };
                                pages.push(pageo);
                            }

                            var row = (pageo.rows.length > 0) ? pageo.rows[pageo.rows.length - 1] : null;
                            if (!row || row.columns.length >= ipr) {
                                row = { columns: [], };
                                pageo.rows.push(row);
                            }

                            row.columns.push({
                                text: obj.label,
                                id: obj.value,
                            });
                        });

                        var startMoment = moment(that.model.get("start"), "YYYY-MM-DD HH:mm:ss");
                        var endMoment = moment(that.model.get("end"), "YYYY-MM-DD HH:mm:ss");

                        //loading the view and appeding it to the views's $el.
                        that.$el.html(tmp(_.extend(that.model.toJSON(), {
                            pages: pages,
                            durationText: that.secondsToHHMMSS(that.model.get("duration")),
                            startDate: startMoment.format("YYYY-MM-DD"),
                            endDate: endMoment.format("YYYY-MM-DD"),
                            startTime: startMoment.format("HH:mm:ss"),
                            endTime: endMoment.format("HH:mm:ss"),
                        })));

                        var dcodes = that.model.get("delayCodes");
                        that.$el.find(".btn-delay-code").each(function (inx, o) {
                            o = $(o);
                            var dcid = o.data("id");
                            var ccode = _.findWhere(delayCodesSelect, { value: dcid });

                            //var dcat = _.find(dcodes, function (obj) {
                            //    return _.isObject(_.findWhere(obj.children, { delayCodeId: dcid })); 
                            //});

                            if (ccode && ccode.color) {
                                o.css("position", "relative");
                                o.append(
                                    $('<div style="width:10px;height:10px;font-size:11px;position:absolute;top:1px;right:6px;"><i class="fa fa-circle" aria-hidden="true"></i></div>')
                                    .css("color", ccode.color).prop("title", ccode.categoryName)
                                );

                                //o.css({
                                //    //"border-top-color": ccode.color,
                                //    "border-bottom-color": ccode.color,
                                //    //"border-left-color": ccode.color,
                                //    //"border-right-color": ccode.color,
                                //    "border-bottom-width": "1px",
                                //    "border-style": "solid"
                                //}); 
                            }
                        });

                        that.options.currentPage = 0;
                        that.options.totalPages = pages.length;
                        that.movePage();
                    }, true, customPath);
                }, customPath, "delay_info_modal_template");
            } else {
                setTimeout(function () {
                    T.render.call(that, that.template, function (tmp) {
                        if (!that.model.get("delayId")) {
                            that.$el.html(tmp());
                        }
                    }, customPath, "delay_info_modal_template_loading");
                }, 500);
            }

            that.options._isRendered = true;
            that.refresh();
        }

        , redrawDelayCodesButtons: function () {
            var that = this;

            var buttonsContainer = this.$el.find('.pages-container');
            var delayCodesSelect = [];
            var ipp = 16; //itemsPerPage
            var ipr = 4; //itemsPerRow
            var pages = [];

            var template = Handlebars.compile(
                '{{#each pages}}' +
                '    <div data-pageNum="{{pageNum}}" class="row-fluid hide">' +
                '        {{#each rows}}' +
                '        <div class="row-fluid text-center" style="margin-top:8px;">' +
                '            {{#each columns}}' +
                '                <div class="span3">' +
                '                    <button style="width:100%;min-height:80px;" data-id="{{id}}" class="btn btn-delay-code">{{text}}</button>' +
                '                </div>' +
                '            {{/each}}' +
                '        </div>' +
                '        {{/each}}' +
                '    </div>' +
                '{{/each}}'
            );


            (function _parseDelayCodesOptions(dict, values, description) {
                for (var i in dict) {
                    var t = dict[i];
                    if (t.children != null) {
                        _parseDelayCodesOptions(t.children, values
                            , (description != null) ? description + ' > ' + t.description : t.description
                        );
                    } else {
                        values.push({
                            value: t.delayCodeId,
                            label: (description != null) ? description + ' > ' + t.description : t.description,
                            frequency: t.frequency,
                            color: t.color,
                            categoryName: t.categoryName,
                        });
                    }
                }
            })(this.model.get("delayCodes"), delayCodesSelect, null);


            //sorting delay codes alphabetically
            delayCodesSelect = _.sortBy(delayCodesSelect, 'label');
            //delayCodesSelect.reverse();

            //Sort delays codes by frequency if this feature is enable.
            if (that.model.get('sortDelayCodesByFrequency') == true) {
                delayCodesSelect = _.sortBy(delayCodesSelect, 'frequency', false);
                delayCodesSelect.reverse();
            }


            //Set pagination variables.
            _.each(delayCodesSelect, function (obj, inx) {
                var page = Math.floor(inx / ipp);
                var pageo;
                if (!(pageo = pages[page])) {
                    pageo = { pageNum: page, rows: [] };
                    pages.push(pageo);
                }

                var row = (pageo.rows.length > 0) ? pageo.rows[pageo.rows.length - 1] : null;
                if (!row || row.columns.length >= ipr) {
                    row = { columns: [], };
                    pageo.rows.push(row);
                }

                row.columns.push({
                    text: obj.label,
                    id: obj.value,
                });
            });


            //Redraw buttons container.
            buttonsContainer
                .empty()
                .html(template({ pages: pages, }));


            //Attach events to DOM objects.
            var dcodes = that.model.get("delayCodes");

            this.$el.find(".btn-delay-code").each(function (inx, o) {
                o = $(o);
                var dcid = o.data("id");
                var ccode = _.findWhere(delayCodesSelect, { value: dcid });

                //var dcat = _.find(dcodes, function (obj) {
                //    return _.isObject(_.findWhere(obj.children, { delayCodeId: dcid })); 
                //});

                if (ccode && ccode.color) {
                    o.css("position", "relative");
                    o.append(
                        $('<div style="width:10px;height:10px;font-size:11px;position:absolute;top:1px;right:6px;"><i class="fa fa-circle" aria-hidden="true"></i></div>')
                        .css("color", ccode.color).prop("title", ccode.categoryName)
                    );

                    //o.css({
                    //    //"border-top-color": ccode.color,
                    //    "border-bottom-color": ccode.color,
                    //    //"border-left-color": ccode.color,
                    //    //"border-right-color": ccode.color,
                    //    "border-bottom-width": "1px",
                    //    "border-style": "solid"
                    //}); 
                }
            });

            //Initialize pagination
            this.options.currentPage = 0;
            this.options.totalPages = pages.length;
            this.movePage();
        }

        , movePage: function (direction) {
            var leftArrow = this.$el.find(".btn-arrow-left");
            var rightArrow = this.$el.find(".btn-arrow-right");
            var currentPage = this.options.currentPage;

            if (direction == 'LEFT') currentPage--;
            else if (direction == 'RIGHT') currentPage++;

            var pages = this.$el.find('*[data-pagenum]');
            pages.addClass("hide");

            this.$el.find('*[data-pagenum="' + currentPage + '"]').removeClass("hide");

            this.options.currentPage = currentPage;

            leftArrow.attr("disabled", false); rightArrow.attr("disabled", false);
            if (currentPage == 0) leftArrow.attr("disabled", true);
            if (currentPage == this.options.totalPages - 1) rightArrow.attr("disabled", true);
        }

        , delayCodeBtn_clicked: function (e) {
            var btn = $(e.target);
            var delaycodeid = btn.data("id");

            if (delaycodeid) {
                this.setDelayCode(delaycodeid);
            }
        }

        , sortDelayCodesByFrequencyCheckbox_changed: function (e) {
            var sortDelayCodesByFrequency = $(e.target).prop('checked');

            this.model.set('sortDelayCodesByFrequency', sortDelayCodesByFrequency);

            localStorage.setItem("delay-information-modal-sortDelayCodesByFrequency", sortDelayCodesByFrequency);

            this.redrawDelayCodesButtons();
        }

        , setDelayCode: function (dcid) {
            var that = this;
            var QP = new Core.Database.QueryParameters();

            var model = this.model;
            QP.Add("Id", "INT", model.get("delayId"));
            QP.Add("DelayCodeID", "INT", dcid);

            app.CallProcedure(app.DatabaseNames.OEE + ".WebApp.SetDelayCode", QP, {
                onSuccess: function (data) {
                    that.trigger("delayCodeSelected");
                    that.hide();
                },
                Secured: true,
            }, app.ConnectionStrings.app);
        }

        , secondsToHHMMSS: function (d) {
            d = Number(d);
            var h = Math.floor(d / 3600);
            var m = Math.floor(d % 3600 / 60);
            var s = Math.floor(d % 3600 % 60);
            return ((h > 0 ? h + " h " : "") + m + " min " + ((s > 0) ? s + " seg" : ""));
        }

        , delayCode_changed: function (e) {
            var el = $(e.target);
            var new_delayCodeId = parseInt(el.val());

            this.model.set("delayCodeId", new_delayCodeId, { silent: true });
        }

        , save: function () {
            var that = this;
            var QP = new Core.Database.QueryParameters();

            var model = this.model;
            QP.Add("Id", "INT", model.get("delayId"));
            QP.Add("DelayCodeID", "INT", model.get("delayCodeId"));

            app.CallProcedure(app.DatabaseNames.OEE + ".WebApp.SetDelayCode", QP, {
                onSuccess: function (data) {
                    that.hide();
                },
                Secured: true,
            }, app.ConnectionStrings.app);
        }

        , refresh: function () {
            try {
                this.model.fetch(this.options.MYREFERENCES.rowData.id);
            } catch (Error) { }
        }
        , show: function () {

            if (!this.options._isRendered) {
                this.render();
                setTimeout(this.show, 100);
                return;
            }

            var self = this,
            $el = this.$el;

            //creating modal
            $el.modal({
                keyboard: false
                , backdrop: "static"
            });

            $backdrop = $('.modal-backdrop');

            $backdrop.one('click', function () {
                if (self.options.content && self.options.content.trigger) {
                    self.options.content.trigger('cancel', self);
                }

                self.trigger('cancel');
            });

            $(document).one('keyup.dismiss.modal', function (e) {
                e.which == 27 && self.trigger('cancel');

                if (self.options.content && self.options.content.trigger) {
                    e.which == 27 && self.options.content.trigger('shown', self);
                }
            });

            this.on('cancel', function () {
                self.hide();
            });

            return this;

        }
        , hide: function () {
            var self = this,
            $el = this.$el;

            $el.one('hidden', function onHidden(e) {
                // Ignore events propagated from interior objects, like bootstrap tooltips
                if (e.target !== e.currentTarget) {
                    return $el.one('hidden', onHidden);
                }

                if (self.options.content && self.options.content.trigger) {
                    self.options.content.trigger('hidden', self);
                }

                self.trigger('hidden');

                self.close();
            });

            $el.modal('hide');
        }
        , bindEvents: function () {
            //this function should be in every view that uses listenTo anywhere
            //all the model bindings or view-model binding should be here, to manage
            //the show/hide view easily

            //rendering as soon as getting data in the model
            this.listenTo(this.model, "change", this.render);
        }
        , close: function () {
            this.remove();
            this.unbind();
        }

        , preRender: function () {
        }

        , reRender: function () {
        }
    });

    return DelayInformationModal; 

}); 