
//SCREEN-BOILERPLATE

//this boilerplate builds screens that are gonna be shown in the <div class="content"> tag of our main HTML.
//do not build app components with this boilerplate, only screens (reports)

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

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

  "modules/modal",

  "backgrid",

  "modules/dateTimeControl",
  "modules/dateControlCasterDelays",

  "moment", 
   'modules/select2-module/select2-module',
  "js/bootstrap-timepicker/js/bootstrap-timepicker",
  "js/bootstrap-select/bootstrap-select",
  "js/bootstrap-slider/bootstrap-slider.min",
    "backgrid/infinator",
   
],

    function (app, T, Modal, Backgrid, DateTimeControl, DateControl, moment, select2Module) {

    //replace all "CasterDelaysManager" with your view's name.
    var CasterDelaysManager = {
        Models: {},
        Views: {},
        Collections: {},
        Config: {
            batchEnabled: false,
        },
    };

    CasterDelaysManager.Models.Main = Backbone.Model.extend({
        defaults: {
            delaySplits: null, 
        }
    });

    //the generate id method is called everytime a view is going to be shown by the router and returns and id that
    //is used by the router to store in cache (if it is cacheable) and to know the current shown view.
    //this is useful in case your view is reusable, and displays different data depending on url parameters 
    //(such as a catalog view, or a report that doesnt change in terms of UI but it does change in terms of data)
    //so you can always use the same view on the router but the cache can tell which view is which by using differents ids.
    CasterDelaysManager.generateID = function (viewParams) {
        try {
            //if the viewparams change the view id, then evaluate the viewparams here
            //and return the appropiate id.
            return "caster-delays-manager"; 
        } catch (Error) { }
    }
    CasterDelaysManager.Models.Delay = Backbone.Model.extend({
        defaults: {
            delayId: null,
            start: null,
            end: null,
            splits: null, //Backbone.Collection of DelaySplit
        }, 
    }); 

    CasterDelaysManager.Models.DelaySplit = Backbone.Model.extend({
        defaults: {
            delayId: null,
            parentId: null,
            line: null, 
            productionItem: null, 
            casterName: null,
            start: null,
            end: null,
            duration: null,
            seconds: null, 
            delayCodeId: null,
            code: null, 
            comments: null,
            batchNumber: null, 
        }, 
    });

    CasterDelaysManager.Collections.Delays = Backbone.Collection.extend({
        model: CasterDelaysManager.Models.Delay,
        fetch: function (e) {
        }, 
    });

    CasterDelaysManager.Collections.DelaySplits = Backbone.Collection.extend({
        model: CasterDelaysManager.Models.DelaySplit,

        fixedcback_onFetch: null,
        fixedcback_onFetchComplete: null,

        fixedParameters: [],
        isFetching: false,
        currentPage: 1,
        pageSize: 40,
        transaction_timestamp: null,

        initialize: function (opt) {
            this.options = _.extend({}, this.options, {
            });

            this.fixedcback_onFetch = (opt && opt.onFetch) ? opt.onFetch : null;
            this.fixedcback_onFetchComplete = (opt && opt.onFetchComplete) ? opt.onFetchComplete : null;
        },
        comparator: function (a, b) {
            var prodItemA = a.get("productionItem");
            var prodItemB = b.get("productionItem");
            var startA = a.get("start");
            var startB = b.get("start");

            if (startA.isAfter(startB)) return -1;
            else if (startA.isBefore(startB)) return 1;
            else return 0; 
        }, 
        fetch: function (params) {
            var that = this;
            var qp = new Core.Database.QueryParameters();

            var ttimestamp = this.transaction_timestamp = new Date().getTime(),
                options = {
                    params: {
                        from: null,
                        to: null,
                        productionItemId: null,
                    },
                    callback: null,
                    refresh: false, 
                }; 

            options = _.extend(options, params); 

            this.isFetching = true;

            if (_.isFunction(this.fixedcback_onFetch))
                this.fixedcback_onFetch.call(this, this, _.extend({}, options));

            if (options.refresh) {
                this.resetPagination(true);

                var crew = null;

                if (options.params.crewId) {
                    if (options.params.crewId == '1') crew = 'A';
                    if (options.params.crewId == '2') crew = 'B';
                    if (options.params.crewId == '3') crew = 'C';
                    if (options.params.crewId == '4') crew = 'D';
                }

                this.fixedParameters = [
                    { Name: '@From', Type: 'DATETIME', Value: options.params.from, },
                    { Name: '@To', Type: 'DATETIME', Value: options.params.to, },
                    { Name: '@Timezone', Type: 'VARCHAR', Value: app.models.user.get("timezoneCode"), },
                    { Name: '@OperatingUnitId', Type: 'INT', Value: options.params.opUnitId, },
                    { Name: '@CauseId', Type: 'INT', Value: options.params.causeId, },
                    { Name: '@AreaId', Type: 'INT', Value: options.params.areaId, },
                    { Name: '@CrewId', Type: 'CHAR', Value: crew, },
                    { Name: '@ShiftId', Type: 'INT', Value: options.params.shiftId, },
                ];
            }

            _.each(this.fixedParameters, function (qpParams) {
                qp.Add(qpParams.Name, qpParams.Type, qpParams.Value);
            });

            if (!options.refresh && !options.set) {
                qp.Add('@fromRow', 'INT', (this.currentPage - 1) * this.pageSize);
                qp.Add('@rowsToFetch', 'INT', this.pageSize);
            } else {
                qp.Add('@fromRow', 'INT', 0);
                qp.Add('@toRow', 'INT', this.currentPage * this.pageSize);
            }

            var ts = this.options.lastFetched = new Date().getTime(); 
            Core.Json.CallProcedure(app.DatabaseNames.MES + ".CAS.GetDelaysCodeGroup", qp, {
                onSuccess: function (data) {
                    if (data && data.Table) {
                        data = data.Table;

                        var delaySplitsModels = [];
                        for (var i = 0, len = data.length; i < len; i++) {

                            var delaySplit = data[i];
                            var delaySplitModel = new CasterDelaysManager.Models.DelaySplit({
                                id: delaySplit.Id,
                                delayId: delaySplit.Id,
                                parentId: delaySplit.ParentId,
                                productionItem: delaySplit.ProductionItem, 
                                casterName: delaySplit.CasterName,
                                start: (delaySplit.Start) ? new moment(delaySplit.Start) : null,
                                end: (delaySplit.End) ? new moment(delaySplit.End) : null,
                                duration: delaySplit.Duration,
                                areaName: delaySplit.AreaName,
                                comments: delaySplit.Comments,
                                causeName: delaySplit.CauseName, 
                                crew: delaySplit.Crew,
                                shift: delaySplit.Shift,
                                seconds: delaySplit.Seconds,
                            });

                            delaySplitsModels.push(delaySplitModel);
                        }

                        if (ttimestamp == that.transaction_timestamp) {
                            var method = (options.set) ? 'set' : 'add';
                            method = (options.method) ? options.method : method; 

                            that[method](delaySplitsModels, { from: "fetch" });

                            //decreasing page since we couldn't get any data on this page.
                            if (delaySplitsModels.length == 0 && method == 'add')
                                that.currentPage--;

                            that.isFetching = false;

                            if (_.isFunction(that.fixedcback_onFetchComplete))
                                that.fixedcback_onFetchComplete.call(that, that, data, options);

                            if (options && options.callback && _.isFunction(options.callback))
                                options.callback.call(that, that, data);
                        }
                    }
                },
                onError: function(){
                    if (options && options.callback && _.isFunction(options.callback))
                        options.callback.call(that, that, data);
                }, 
                Secured: true, 
            }, app.ConnectionStrings.app);
        },
        getNextPage: function (options) {
            if (!this.isFetching) {
                this.currentPage++;
                options = (_.isObject(options)) ? options : {};
                this.fetch(options);
            }
        },
        resetPagination: function (force) {
            if (!this.isFetching || force == true) {
                this.currentPage = 1;
            } else {
                _.delay(this.resetPagination, 100);
            }
        },
    });

    CasterDelaysManager.Views.Main = Backbone.View.extend({
        template: "caster-delays-manager"
        , id: "caster-delays-manager"
        , title: "Caster Delays Manager"
        //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: false
        , events: function () {
            return {
                'click #refreshBtn': this.refreshBtn_click,
                'click #printBtn': this.printBtn_click,
                'click #forwardNavBtn': this.forwardNavBtn_click,
            };
        }
        , pauseTimer: false
        , initialize: function () {
            this.options.state = app.view_states.loading;
            this.options.onappend = (_.isFunction(this.options.onappend)) ? this.options.onappend : function () { };

            if (this.options.viewParams) {
            }

            var model = new CasterDelaysManager.Models.Main({
                delaySplits: new CasterDelaysManager.Collections.DelaySplits({
                    onFetch: _.bind(this.fixedCallback_onFetch, this),
                    onFetchComplete: _.bind(this.fixedCallback_onFetchComplete, this), 
                }),
            });

            this.bus = _.extend({}, Backbone.Events);
            this.bus.on("delaySplitted", this.onDelaySplitted, this);
            this.options.MYREFERENCES = {
                subviews: {
                }
                , autoRefresh: {
                    enabled: true
                    , toid: null
                }
            };

            this.options.grids = {
                delaysGrid: null, 
            }; 
            this.newDelayIdSplitted = null;
            this.model = model;

            this.options.MYREFERENCES.subviews.subnavbarControls = new CasterDelaysManager.Views.SubnavBarControls({
                parent: this
                , model: new CasterDelaysManager.Models.SubnavBarControls()
                , container: app.views.subnavbar.getSectionContainer(1, 12)
                , onExportToExcel: _.bind(this.exportToExcel, this),
            });

            this.options.MYREFERENCES.subviews.subnavbarControls.render();

            this.bindEvents();
            //this.$el.on('click', '.dropdown-toggle', this.dropdownToggleClicked);
            
            _.bindAll(this);
        },

        render: function (container) {
            var that = this;
            var thatContainer = (container != null && container != undefined) ? container : this.options.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/custom-screens/caster-delays-manager/";

            T.render.call(this, this.template, function (tmp) {
                //getInternationalizationData
                if (!that.options.i18n) that.options.i18n = {};
                app.getI18NJed(that, that.template, function (i18nJED) {
                    //storing internationalization data
                    that.options.i18n[that.template] = i18nJED;
                    that.$el.html(tmp());

                    var ActionsCell = Backgrid.Cell.extend({
                        template: Handlebars.compile(that.$el.find("script#actions_cell_template").html()),
                        events: {
                            "click .action-source-btn": function (e) {
                                e.preventDefault();
                            },
                            "click .btn-dropdown-action-option": "configure_dropdown_action_opt_click",
                            "click .dropdown-toggle-btn": function (e) {
                                e.preventDefault();
                                that._stopAutoRefresh();
                            },

                        },
                        initialize: function () {
                            Backgrid.Cell.prototype.initialize.apply(this, arguments);

                            _.bindAll(this);
                            this.bindEvents();
                        },
                        render: function () {
                            Backgrid.Cell.prototype.render.apply(this, arguments);

                            this.$el.html(this.template({
                                join: this.model.get("parentId") ? true : false,
                                split: this.model.get("end") ? true : false, 
                            }));

                            this.checkAnyOptions();
                            this.delegateEvents();
                            return this;
                        },
                        checkAnyOptions: function () {
                            var actionSourceBtn = this.$el.find(".action-source-btn");
                            if (this.$el.find(".action-source-dropdown").find("li").length > 0) {

                                // check if the delay is within the 24 hours in case got operator Role. 
                                //look for operator Role
                                var isOperator = $.inArray('cdm_op', app.models.user.get('roles')) != -1 ? true : false;

                                if (isOperator) {
                                    var now = moment();
                                    var minsDifference = now.diff(this.model.get('end'), 'minutes');
                                    //24 hours
                                    if (minsDifference > 1440) {
                                        actionSourceBtn.attr("disabled", true);
                                    }
                                    else {
                                        actionSourceBtn.attr("disabled", false);
                                    }
                                }
                                else {
                                    actionSourceBtn.attr("disabled", false);
                                }
                               
                            } else {
                                actionSourceBtn.attr("disabled", true);
                            }
                        },
                        configure_dropdown_action_opt_click: function (e) {
                            e.preventDefault();
                            if (!$(e.target).hasClass("disabled-link")) {
                                that.actionOnRow(this.model, { option: $(e.target).data("option") });
                            }
                        },
                        bindEvents: function () {
                        },
                    });

                    var SplitButtonCell = Backgrid.Cell.extend({
                        template: _.template('<button data-preventclick="true" class="btn split-btn" style="font-size: 13px !important;font-weight:bold;color:#505050;width:80px">Split</button>'),

                        events: {
                            'click .split-btn': 'openSplitModal'
                        },

                        render: function () {
                            this.$el.html(this.template());
                            this.checkAnyOptions();
                            this.delegateEvents();
                            return this;
                        },
                        checkAnyOptions: function () {
                            var splitBtn = this.$el.find(".split-btn");
                            
                            if (this.model.get('end') != null) {
                                // check if the delay is within the 24 hours in case got operator Role. 
                                //look for operator Role
                                var isOperator = $.inArray('cdm_op', app.models.user.get('roles')) != -1 ? true : false;
                                if (isOperator) { 
                                    var now = moment();
                                    var minsDifference = now.diff(this.model.get('end'), 'minutes');
                                    // 24 hrs
                                    if (minsDifference > 1440) {
                                        splitBtn.attr("disabled", true);
                                    }
                                    else {
                                        splitBtn.attr("disabled", false);
                                    }
                                }
                                else {
                                    splitBtn.attr("disabled", false);
                                }
                                
                            } else {
                                splitBtn.attr("disabled", true);
                            }
                        },

                        openSplitModal: function (e) {
                            that.actionOnRow(this.model, { option: 'ds-split' });
                        }
                    });
                    var columns = [
                        {
                            name: "start",
                            label: 'Start',
                            editable: false,
                            sortable: false,
                            cell: Backgrid.StringCell.extend({
                                orderSeparator: '',
                                formatter: _.extend({}, Backgrid.CellFormatter.prototype, {
                                    fromRaw: function (rawValue, model) {
                                        var formatted = (rawValue != null && rawValue.format) ? rawValue.format("MM/DD HH:mm:ss") : rawValue;
                                        return formatted;
                                    }
                                }),
                                className: "string-cell align-center-cell",
                            })
                        },
                        {
                            name: "end",
                            label: app.translate(that, "end_label"),
                            editable: false,
                            sortable: false,
                            cell: Backgrid.StringCell.extend({
                                orderSeparator: '',
                                className: "string-cell align-center-cell",
                                formatter: _.extend({}, Backgrid.CellFormatter.prototype, {
                                    fromRaw: function (rawValue, model) {
                                        var formatted = (rawValue != null && rawValue.format) ? rawValue.format("MM/DD HH:mm:ss") : rawValue;
                                        return formatted;
                                    }
                                }),
                                render: function () {
                                    Backgrid.StringCell.prototype.render.apply(this, arguments);
                                    if (this.model.get("end") == null) {
                                        this.$el.text("...");
                                    }
                                    return this;
                                },
                            })
                        },
                        {
                            name: "duration",
                            label: app.translate(that, "duration_label"),
                            editable: false,
                            sortable: false,
                            cell: Backgrid.StringCell.extend({
                                orderSeparator: '',
                                className: "string-cell align-center-cell",
                                render: function () {
                                    Backgrid.StringCell.prototype.render.apply(this, arguments);
                                    if (this.model.get("duration") == null) {
                                        this.$el.text("...");
                                    }
                                    return this;
                                },
                            })
                        },
                        {
                            name: "shift",
                            label: 'Shift',
                            editable: false,
                            sortable: false,
                            cell: Backgrid.StringCell.extend({
                                orderSeparator: '',
                                className: "string-cell align-center-cell",
                            })
                        },
                        {
                            name: "crew",
                            label: 'Crew',
                            editable: false,
                            sortable: false,
                            cell: Backgrid.StringCell.extend({
                                orderSeparator: '',
                                className: "string-cell align-center-cell",
                            })
                        },
                        {
                            name: "casterName",
                            label: app.translate(that, "machine_label"),
                            editable: false,
                            sortable: false,
                            cell: Backgrid.StringCell.extend({
                                orderSeparator: '',
                                className: "string-cell align-center-cell",
                            })
                        },   
                        {
                            name: "causeName",
                            label: 'Cause',
                            editable: false,
                            sortable: false,
                            cell: Backgrid.StringCell.extend({
                                orderSeparator: '',
                                className: "string-cell align-center-cell",
                            })
                        },
                        {
                            name: "areaName",
                            label: app.translate(that, "areaName_label"),
                            editable: false,
                            sortable: false,
                            formatter: _.extend({}, Backgrid.CellFormatter.prototype, {
                                fromRaw: function (rawValue, model) {
                                    return (rawValue) ? app.translate(that, rawValue) : rawValue;
                                }
                            }),
                            cell: Backgrid.StringCell.extend({
                                orderSeparator: '',
                                className: "string-cell align-center-cell",
                            })
                        },
                        {
                            name: "comments",
                            label: app.translate(that, "comments_label"),
                            editable: false,
                            sortable: false,
                            cell: Backgrid.StringCell.extend({
                                orderSeparator: '',
                                className: "string-cell align-center-cell",
                            }),
                            formatter: _.extend({}, Backgrid.CellFormatter.prototype, {
                                fromRaw: function (rawValue, model) {
                                    var maxChars = 40; 
                                    var formatted = (rawValue) ? rawValue : "";
                                    if (formatted && formatted.length > maxChars)
                                        formatted = formatted.substring(0, maxChars - 3) + "...";

                                    return formatted; 
                                }
                            })
                        },
                        {
                            name: "configure",
                            label: "",
                            sortable: false,
                            editable: false,
                            headerCell: Backgrid.HeaderCell.extend({
                                className: "configuretd",
                            }),
                            cell: ActionsCell,
                        }, 
                        {
                            name: "configure",
                            label: "",
                            sortable: false,
                            editable: false,
                            headerCell: Backgrid.HeaderCell.extend({
                                className: "configuretd",
                            }),
                            cell: SplitButtonCell,
                        }, 
                    ]; 

                    var CustomRow = Backgrid.Row.extend({
                        events: {
                            "click": "onClick"
                        },
                        className: "clickeable-row",
                        onClick: function (e) {
                            var target = $(e.target); 
                            var data_prevent = (target.closest("[data-preventclick]").length > 0) ? target.closest("[data-preventclick]").data("preventclick") : false; 

                            if (!data_prevent) {
                                that.showDelayInfoModal(this.model); 
                            }
                        }
                    });

                    // Initialize a new Grid instance
                    var delays_grid;
                    delays_grid = that.options.grids.delaysGrid = new Backgrid.Grid({
                        row: CustomRow, 
                        className: "backgrid table table-hover",
                        columns: columns,
                        collection: that.model.get("delaySplits"),
                        footer: Backgrid.Extension.Infinator.extend({
                            scrollToTop: false,
                        }),
                    });

                    that.$el.find(".delays-grid-container").append(delays_grid.render().el);

                    that.append(thatContainer, that.$el);

                    that._startAutoRefresh({ showLoading: true, refresh: true });

                    //that._autoRefresh({ showLoading: true, refresh: true }); 

                    $(document).click(function (event) {
                        // Check if the clicked element is the button
                        if ($(event.target).closest('#open-dropdown-btn').length) {
                            // Clicked on the button
                        } else {
                            // Clicked outside the button
                            that._startAutoRefresh();

                            // If you want to hide the dropdown when clicked outside
                            // $('#open-dropdown-btn').dropdown('hide');
                        }
                    });
                }, true, customPath);
            }, customPath, "main_template");
        }

        , actionOnRow: function (model, data) {
            switch (data.option) {
                case "ds-edit":
                    this.showDelayInfoModal(model); 
                    break;
                case "ds-split":
                    this.showDelaySplitModal(model); 
                    break;
                case "ds-join":
                    this.joinDelay(model); 
                    break; 
            }
        }

        , onDelaySplitted: function (delayIds) {
            this.newDelayIdSplitted = delayIds?.Table[0]?.d2
        }
        , splitReady: function () {
            var newDelay = this.newDelayIdSplitted;
            var models = that.model.get("delaySplits").models;
            var m = _.findWhere(models, { id: newDelay });

            this.showDelayInfoModal(m);
            this.newDelayIdSplitted = null;
        }
        , showDelayInfoModal: function (m) {
            var that = this; 
            var delayinfomodal = new CasterDelaysManager.Views.DelaySplitInformationModal({
                viewParams: {
                    rowData: {
                        id: m.get("delayId"),
                        model: m,
                        delayCategories: this.options.MYREFERENCES.subviews.subnavbarControls.model.get("delayCategories"),
                    },
                },
                parent: that,
            });

            //calling grid refresh as soon as the modal is hidden in case
            //any changes were made.
            delayinfomodal.on("hidden", this._autoRefresh);

            delayinfomodal.show();
        }

        , showDelaySplitModal: function (m) {
            var that = this;
            var delaysplitmodal = new CasterDelaysManager.Views.SplitDelay({
                viewParams: {
                    rowData: {
                        id: m.get("delayId"),
                        model: m,
                    },
                },
                model: new CasterDelaysManager.Models.SplitDelay({
                    id: m.get("delayId"),
                    start: m.get("start"),
                    end: m.get("end"),
                    duration: m.get("seconds"),
                }),

                bus: that.bus,
            });

            //calling grid refresh as soon as the modal is hidden in case
            //any changes were made.
            delaysplitmodal.on("delaySplitted", this.onDelaySplitted); 
            delaysplitmodal.on("hidden", this._autoRefresh);
            delaysplitmodal.show();
        }

        , joinDelay: function (model) {
            var that = this; 
            CasterDelaysManager.Views.DelaySplitInformationModal.joinDelay(model.get("delayId"), function () {
                that._autoRefresh(); 
            });
        }

        , _startAutoRefresh: function (opt) {
            try {
                if (this.options.MYREFERENCES.autoRefresh.toid != null) {
                    clearTimeout(this.options.MYREFERENCES.autoRefresh.toid);
                    this.options.MYREFERENCES.autoRefresh.toid = null;
                }

                this.options.MYREFERENCES.autoRefresh.enabled = true;

                this._autoRefresh(opt);
            } catch (Error) { }
        }

        , _autoRefresh: function (opt) {
            var that = this; 
            if (this.options.MYREFERENCES.autoRefresh.toid != null) {
                clearTimeout(this.options.MYREFERENCES.autoRefresh.toid);
                this.options.MYREFERENCES.autoRefresh.toid = null;
            }
            this.refresh(_.extend({}, opt, {
                callback: function () {
                    if (that.options.MYREFERENCES.autoRefresh.enabled == true) {
                        that.options.MYREFERENCES.autoRefresh.toid = setTimeout(that._autoRefresh, 5000);
                    }
                }, 
            }));
        }

        , _stopAutoRefresh: function () {
            if (this.options.MYREFERENCES.autoRefresh.toid != null) {
                clearTimeout(this.options.MYREFERENCES.autoRefresh.toid);
                this.options.MYREFERENCES.autoRefresh.toid = null;
            }
            this.options.MYREFERENCES.autoRefresh.enabled = false;
        }

        , keepRefreshingTillScreenFilled: function (resp, collectionName) {
            var that = this;
            if (!this.isScreenFilled() && resp.length > 0) {
                this.model.get(collectionName).getNextPage({
                    success: function (col, resp, opt) {
                        that.keepRefreshingTillScreenFilled(resp, collectionName);
                    }
                });
            }
        }

        , isScreenFilled: function () {
            var getWindowSize = (function () {
                var docEl = document.documentElement,
                    IS_BODY_ACTING_ROOT = docEl && docEl.clientHeight === 0,
                    b = document.body;

                // Used to feature test Opera returning wrong values
                // for documentElement.clientHeight.

                function isDocumentElementHeightOff() {
                    var d = document,
                        div = d.createElement('div'),
                        r;
                    div.style.height = "50000px";
                    d.body.insertBefore(div, d.body.firstChild);
                    r = d.documentElement.clientHeight > 49000;
                    d.body.removeChild(div);
                    return r;
                }

                if (typeof document.clientWidth === "number") {
                    return function () {
                        return {
                            width: document.clientWidth,
                            height: document.clientHeight
                        };
                    };
                } else if (IS_BODY_ACTING_ROOT || isDocumentElementHeightOff()) {
                    return function () {
                        return {
                            width: b.clientWidth,
                            height: b.clientHeight
                        };
                    };
                } else {
                    return function () {
                        return {
                            width: docEl.clientWidth,
                            height: docEl.clientHeight
                        };
                    };
                }
            })();

            var body = document.body, html = document.documentElement;

            var documentHeight = Math.max(body.scrollHeight, body.offsetHeight,
                                   html.clientHeight, html.scrollHeight, html.offsetHeight);

            return (!(getWindowSize().height >= documentHeight));
        }

        , fixedCallback_onFetch: function (ref, opt) {
            if (!opt.set && !opt.refresh) {
                this.infscroll_loading(true); 
            }
        }
        , fixedCallback_onFetchComplete: function (ref, data, opt) {
            this.infscroll_loading(false); 
        }
        , infscroll_loading: function (val) {
            var p = this.$el.find(".infinite-scrolling-loading-poster");
            if (val) p.removeClass("hide");
            else p.addClass("hide"); 
        }

        , refresh: function (opt) {
            try {
                var that = this;
                var fetched = false; 
                if (opt && opt.showLoading) {
                    setTimeout(function () {
                        if (!fetched) that.showLoading(true);
                    }, 500);
                }

                var lineId = this.options.MYREFERENCES.subviews.subnavbarControls.model.get("lineProductionItemId");
                var opUnitId = this.options.MYREFERENCES.subviews.subnavbarControls.model.get("operatingUnitId");
                var areaId = this.options.MYREFERENCES.subviews.subnavbarControls.model.get("areaId");
                var causeId = this.options.MYREFERENCES.subviews.subnavbarControls.model.get("causeId");
                var shiftId = this.options.MYREFERENCES.subviews.subnavbarControls.model.get("shiftId");
                var crewId = this.options.MYREFERENCES.subviews.subnavbarControls.model.get("crewId")
                var opUnitIdFilter = (opUnitId != -1) ? opUnitId : null;
                var areaIdFilter = (areaId != -1) ? areaId : null;
                var causeIdFilter = (causeId != -1) ? causeId : null;
                var shiftIdFilter = (shiftId != -1) ? shiftId : null;
                var crewIdFilter = (crewId != -1) ? crewId : null;


                this.model.get("delaySplits").fetch({
                    params: {
                        from: this.options.MYREFERENCES.subviews.subnavbarControls.model.get("from"),
                        to: this.options.MYREFERENCES.subviews.subnavbarControls.model.get("to"),
                        opUnitId: opUnitIdFilter,
                        timezone: app.models.user.get("timezoneCode"),
                        areaId: areaIdFilter,
                        causeId: causeIdFilter,
                        shiftId: shiftIdFilter,
                        crewId: crewIdFilter,
                    },
                    callback: function (a, r) {
                        fetched = true; 
                        that.showLoading(false);

                        if (opt && opt.callback && _.isFunction(opt.callback))
                            opt.callback.call(that, that);

                        that.keepRefreshingTillScreenFilled(r, "delaySplits");

                        if (that.newDelayIdSplitted) {
                            var newDelay = that.newDelayIdSplitted;
                            that.newDelayIdSplitted = null;
                            var models = that.model.get("delaySplits").models;
                            var m = _.findWhere(models, { id: newDelay });

                            that.showDelayInfoModal(m);
                            that.newDelayIdSplitted = null;
                        }
                    },
                    refresh: (opt && opt.refresh) ? true : false,
                    set: true, 
                });
            } catch (Error) { }
        }
       
        , exportToExcel: function () {
            var that = this;
            this.options.MYREFERENCES.subviews.subnavbarControls.setExportButtonExporting(true);

            var lineId = this.options.MYREFERENCES.subviews.subnavbarControls.model.get("lineProductionItemId");
            var machineId = this.options.MYREFERENCES.subviews.subnavbarControls.model.get("operatingUnitId");
            var shiftId = this.options.MYREFERENCES.subviews.subnavbarControls.model.get("shiftId");
            var crewId = this.options.MYREFERENCES.subviews.subnavbarControls.model.get("crewId");
            var delayCategoryId = this.options.MYREFERENCES.subviews.subnavbarControls.model.get("delayCategoryId");
            var productionItemIdFilter = (lineId != -1) ? (machineId != -1) ? machineId : lineId : (machineId != -1) ? machineId : null;
            var shiftIdFilter = (shiftId != -1) ? shiftId : null;
            var crewIdFilter = (crewId != -1) ? crewId : null;
            var delayCategoryIdFilter = (delayCategoryId != -1) ? delayCategoryId : null;



            var crew = null;

            if (crewId) {
                if (crewId == '1') crew = 'A';
                if (crewId == '2') crew = 'B';
                if (crewId == '3') crew = 'C';
                if (crewId == '4') crew = 'D';
            }

           

            var params = [
                { Name: '@From', Type: 'DATETIME', Value: this.options.MYREFERENCES.subviews.subnavbarControls.model.get("from"), },
                { Name: '@To', Type: 'DATETIME', Value: this.options.MYREFERENCES.subviews.subnavbarControls.model.get("to"), },
                { Name: '@ProductionItemId', Type: 'INT', Value: productionItemIdFilter, },
                { Name: '@Timezone', Type: 'VARCHAR', Value: app.models.user.get("timezoneCode"), },
                { Name: '@ShiftId', Type: 'INT', Value: shiftIdFilter, },
                { Name: '@CrewId', Type: 'INT', Value: crewIdFilter ? crew : null, },
                { Name: '@delayCategoryId', Type: 'INT', Value: delayCategoryIdFilter, },
            ];

            var QP = new QueryParameters();

            _.each(params, function (qpParams) {
                QP.Add(qpParams.Name, qpParams.Type, qpParams.Value);
            });


            var data = { 
                    Data: [],
                    ConnectionStringName: 'APP',
                    ExportMethod: 3,
                    FileName: 'DelaysReport',
                    TemplateFileFullPath: 'generic.xls',
                    SQLDataSources: [
                        {
                            Name: 'data',
                            DatabaseParameters: {
                                DBEngine: 'SQLSERVER',
                                Procedure: app.DatabaseNames.MES + '.CAS.GetDelaysCodeGroup',
                                QueryParameters: QP,
                            },
                        },
                    ]
                },
                chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
                chari = 0;

            data.Data.push({
                SheetName: 'Data',
                RowsData: [{
                    CellsData: [].concat(
                        [
                            { Column: chars[chari++], Value: 'Date' },
                            { Column: chars[chari++], Value: 'Shift' },
                            { Column: chars[chari++], Value: 'Crew' },
                            { Column: chars[chari++], Value: 'Furnace' },
                            { Column: chars[chari++], Value: 'Start' },
                            { Column: chars[chari++], Value: 'End' },
                            { Column: chars[chari++], Value: 'Duration' },
                            { Column: chars[chari++], Value: 'Code Group' },
                            { Column: chars[chari++], Value: 'Code' },
                            { Column: chars[chari++], Value: 'Comments' },
                        ],
                    ),
                }],
                StartRowIndex: 1,
            });

            chari = 0;

            data.Data.push({
                SheetName: 'Data',
                RowsData: [],
                StartRowIndex: 2,
                DataSourceName: 'data',
                DataSourceTableIndex: 0,
                SQLCellsData: [].concat(
                    [
                        { ExcelColumnName: chars[chari++], SQLDataColumnName: 'Date', DataType: 'String' },
                        { ExcelColumnName: chars[chari++], SQLDataColumnName: 'Shift', DataType: 'String' },
                        { ExcelColumnName: chars[chari++], SQLDataColumnName: 'Crew', DataType: 'String' },
                        { ExcelColumnName: chars[chari++], SQLDataColumnName: 'Furnace', DataType: 'String' },
                        { ExcelColumnName: chars[chari++], SQLDataColumnName: 'Start', DataType: 'String' },
                        { ExcelColumnName: chars[chari++], SQLDataColumnName: 'End', DataType: 'String' },
                        { ExcelColumnName: chars[chari++], SQLDataColumnName: 'CodeGroup', DataType: 'String' },
                        { ExcelColumnName: chars[chari++], SQLDataColumnName: 'Code', DataType: 'String' },
                        { ExcelColumnName: chars[chari++], SQLDataColumnName: 'Comments', DataType: 'String' },
                    ],
                ),
            });


            Core.Export.Excel(
                data,
                function (resp) {
                    try {
                        if ((resp) && (resp.Success == true) && (resp.Data)) {
                            location.href = app.foldersRoot + '/excel/' + resp.Data;
                        }
                        else {
                            if ((resp) && (resp.Message))
                                console.error(resp.Message);
                            else
                                console.error('Server response not valid.');
                        }
                    }
                    catch (Error) { console.error(Error); }
                    that.options.MYREFERENCES.subviews.subnavbarControls.setExportButtonExporting(false);
                },
                function (resp) {
                    that.options.MYREFERENCES.subviews.subnavbarControls.setExportButtonExporting(false);
                    console.error(resp);
                }
            );
        }

        , showLoading: function (val) {
            var loadingPoster = this.$el.find(".loading-poster"); 
            var gridContainer = this.$el.find(".delays-grid-container"); 
            
            if (val) {
                gridContainer.addClass("hide");
                loadingPoster.removeClass("hide");
            } else {
                loadingPoster.addClass("hide");
                gridContainer.removeClass("hide"); 
            }
        }

        , filtersChanged: _.debounce(function(){
            this._autoRefresh({ showLoading: true, refresh: true }); 
        }, 500)

        , append: function (container, el) {
            el = (el != null && el != undefined) ? el : this.$el;

            if (this.options.state == app.view_states.loading
                || this.options.state == app.view_states.shown) {
                //appending view to the main container and set state to shown

                this.options.state = app.view_states.shown;
                container.append(el);

                this.options.onappend(this);
            }

            if (this.options.state == app.view_states.hidden) {
                //append and remain hidden
                container.append(el);
            }

            if (this.options.state == app.view_states.closed) {
                //return without appending.
                return;
            }
        }

        , 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
            var that = this;
            this.listenTo(this.options.MYREFERENCES.subviews.subnavbarControls.model, "change:from", this.filtersChanged);
            this.listenTo(this.options.MYREFERENCES.subviews.subnavbarControls.model, "change:to", this.filtersChanged);
            this.listenTo(this.options.MYREFERENCES.subviews.subnavbarControls.model, "change:operatingUnitId", this.filtersChanged);
            this.listenTo(this.options.MYREFERENCES.subviews.subnavbarControls.model, "change:areaId", this.filtersChanged);
            this.listenTo(this.options.MYREFERENCES.subviews.subnavbarControls.model, "change:causeId", this.filtersChanged);
            this.listenTo(this.options.MYREFERENCES.subviews.subnavbarControls.model, "change:crewId", this.filtersChanged);
            this.listenTo(this.options.MYREFERENCES.subviews.subnavbarControls.model, "change:shiftId", this.filtersChanged);
        }

        , bindViewScopedEvents: function () {
            var that = this; 
        }

        , unbindViewScopedEvents: function () {
            for (var g in this.options.grids) {
                if (this.options.grids[g].footer &&
                    this.options.grids[g].footer.setEnabled) {
                    this.options.grids[g].footer.setEnabled(false);
                }
            }
            this._stopAutoRefresh(); 
        }

        , close: function () {
            this.options.state = app.view_states.closed;

            this.closeSubviews(); 
            this.remove();
            this.unbindViewScopedEvents();
            this.unbind();
        }

        , closeSubviews: function () {
            _.each(this.options.MYREFERENCES.subviews, function (sview) {
                sview.close();
            });
        }

        , show: function () {
            this.options.state = app.view_states.shown;

            this.showSubviews(); 
            this.bindEvents();
            this.$el.show();

            // Bind the event directly

        }

        , showSubviews: function () {
            _.each(this.options.MYREFERENCES.subviews, function (sview) {
                sview.show();
            });
        }

        , hide: function () {
            this.options.state = app.view_states.hidden;

            this.hideSubviews();
            this._stopAutoRefresh(); 

            this.$el.hide();
            this.unbind();
            this.stopListening();
        }

        , hideSubviews: function () {
            _.each(this.options.MYREFERENCES.subviews, function (sview) {
                sview.hide();
            });
        }

        , preRender: function () {
            app.models.subnavbar.setAll(false);
            app.models.subnavbar.set("subnavbar", true);
            app.models.subnavbar.set("sections", "12");
        }

        , reRender: function () {
            this._startAutoRefresh(); 
        }
    });

    CasterDelaysManager.Models.DelaySplitInformationModal = Backbone.Model.extend({
        defaults: {
            delayId: null,
            parentId: null,
            line: null,
            productionItem: null,
            start: null,
            end: null,
            startTime: null,
            endTime: null,
            duration: null,
            delayCodeId: null,
            comments: null,


            //behind the scenes
            delayCodes: null,
            batchIds: null, 
        },
        initialize: function () {
            this.options = {
                fetched: false,
            }; 
        },
        fetch: function (delayId) {
            var that = this;
            var QP = new Core.Database.QueryParameters();
            QP.Add("DelayID", "INT", delayId);

            Core.Json.CallProcedure(app.DatabaseNames.MES + ".CAS.GetDelayData", QP, {
                onSuccess: function (data) {
                    if (data && data.Table && data.Table.length > 0) {                      

                        data = data.Table[0];

                        var values = _.extend({}, that.attributes, {
                            delayId: data.DelayId,
                            parentId: data.ParentId,
                            line: data.Line,
                            productionItem: data.ProductionItem, 
                            start: data.Start,
                            end: data.End,
                            startTime: data.StartTime,
                            endTime: data.EndTime,
                            duration: data.Duration,
                            delayCodeId: (data.DelayCodeID != null) ? data.DelayCodeID : -1,
                            comments: data.Comments,
                            batchId: data.BatchId, 
                        });

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

    CasterDelaysManager.Views.DelaySplitInformationModal = Backbone.View.extend({
        template: "caster-delays-manager"
        , id: "caster-delays-manager"
        , 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._isRendered = false;

            this.model = new CasterDelaysManager.Models.DelaySplitInformationModal();

            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-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(); 
            }

            , "keyup .comments-textarea": "comments_changed"
            , "change .delaycodes-select": "delayCode_changed"
            , "change .batchIds-select": "batchId_changed"
            , "shown.bs.modal": "modal_shown"
            //, "click #delay_info_modal_delete_split_btn": "removeDelaySplit"
            //, "click #delay_info_modal_split_btn": "splitDelay"
            //, "click #delay_info_modal_join_btn": "joinDelay"
        },
        render: function (container) {
            var that = this;
            var thatContainer = container;

            //if (!this.model.options.fetched) {
            //    return; 
            //}

            //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/custom-screens/caster-delays-manager/";

            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;
                       
                        //loading the view and appeding it to the views's $el.
                        that.$el.html(tmp(_.extend(that.model.toJSON(), {
                            durationText: that.model.get("duration") ? that.secondsToHHMMSS(that.model.get("duration")) : "...",
                            showBatchSelect: false,
                        })));


                        var defaultOptions = {
                            template: 'dropdown'
                            , minuteStep: 1
                            , secondStep: 1
                            , showSeconds: true
                            , defaultTime: false
                            , showMeridian: false
                        };

                        that.$el.find(".datetime-picker").each(function () {
                            var el = $(this);
                            var modelattr = el.data("modelattr");
                            var datetimecontrol_model = new DateTimeControl.Model({
                                datetime: null
                            });

                            //that.listenTo(datetimecontrol_model, "change:datetime", function () {
                            //    var args = arguments;
                            //    that.datetime_changed.call(this, modelattr, args);
                            //});

                            var datetimecontrol_view = new DateTimeControl.Views.Main({
                                model: datetimecontrol_model,
                                datepicker_options: {
                                }, 
                            });

                            datetimecontrol_view.render(el, function (ref) {
                                ref.$el.find("#datetime_datePicker").prop("disabled", true);
                                ref.$el.find("#datetime_timePicker").prop("disabled", true);
                            });

                            if (modelattr && that.model.get(modelattr)) {
                                datetimecontrol_model.set("datetime", that.model.get(modelattr));
                            }
                        });

                    }, true, customPath); 

                }, customPath, "delay_split_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_split_info_modal_loading");
                }, 500); 
            }

            that.options._isRendered = true;
            that.refresh(); 
        }
        , convertEquipment: function (rawDelayCode, parentId = null) {
            var that = this;
            const result = [];
            _.each(rawDelayCode, function (item) {
                if (item.parentId === parentId) {
                    const newItem = { id: item.id, text: item.text, inc: that.convertEquipment(rawDelayCode, item.id) };
                    result.push(newItem);
                }
            });

            return result;
        }

        , renderSelectInputs: function () {

            var that = this;
            //Filter to show only options of the corresponding caster
            var delayCodeFiltered = this.options.MYREFERENCES.rowData.delayCategories.filter(x => x.rootId == 1);

            // parent codes for select
            var parentDelayCodes = delayCodeFiltered.filter(x => x.parentId == null);
            parentDelayCodes.push({ id: -1, parentId: null, text: "Not Declared" });

          
            const parentSelectElement = document.getElementById('parentDelaySelect');

            var parentDelayCodeSelected = -1
            // set to not declared if not find the correspondent delayId
            if (delayCodeFiltered.filter(x => x.id == that.model.get('delayCodeId')).length > 0) {
                parentDelayCodeSelected = delayCodeFiltered.filter(x => x.id == that.model.get('delayCodeId'))[0].parentId;
            }
           
            parentDelayCodes.forEach(code => {
                const option = document.createElement('option');
                option.value = code.id;
                option.text = code.text;

                if (code.id === parentDelayCodeSelected) {
                    option.selected = true;
                }
                parentSelectElement.appendChild(option);
            });

            
            parentSelectElement.addEventListener('change', function () {
                
                that.renderAreaInputs();
            });

            this.renderAreaInputs();
        },
        renderAreaInputs: function () {

            var that = this;
            //Filter to show only options of the corresponding caster
            var delayCodeFiltered = this.options.MYREFERENCES.rowData.delayCategories.filter(x => x.rootId == 1);

            var parentDelayCodeSelected = document.getElementById('parentDelaySelect').value

            const areaSelectElement = document.getElementById('childDelaySelect');
            areaSelectElement.innerHTML = '';

            // area codes for select
            var areaDelayCodes = delayCodeFiltered.filter(x => x.parentId == parentDelayCodeSelected);
            areaDelayCodes.push({ id: -1, parentId: -1, text: "Not Declared" });


            areaDelayCodes.forEach(code => {
                const option = document.createElement('option');
                option.value = code.id;
                option.text = code.text;

                if (code.id === that.model.get('delayCodeId')) {
                    option.selected = true;
                }
                areaSelectElement.appendChild(option);
            });


        }
        //, renderSelectInputs: function () {

        //    var that = this;
        //    var eqpData = this.convertEquipment(this.options.MYREFERENCES.rowData.delayCategories);
        //    const equipmentSelect = new CasterDelaysManager.Views.Select({
        //        selectType: 'tree',
        //        el: '#treeSelectContainer',
        //        data: eqpData,
        //        disabledByDefault: false,
        //    });

        //    //This is the way to set the value of a select2totree element
        //    const delayCodeId = that.model.get('delayCodeId');
        //    $('#treeSelectContainer').val(delayCodeId).trigger('select2:select');
        //    var selectedOption = $('#treeSelectContainer').find('option:selected');
        //    var selectedLabel = selectedOption.text();
        //    $('.select2-selection__rendered').text(selectedLabel);


        //}

        , modal_shown: function (e) {
            try {
                //this.renderSelectInputs(this.options.MYREFERENCES.rowData.delayCategories);
                this.renderSelectInputs();
            }
            catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
        },
        
         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" : ""));
        }

        , datetime_changed: function (modelattr, args) {
            var new_datetime = args[1]; 
            this.model.set(modelattr, new_datetime, { silent: true });
        }

        , comments_changed: function (e) {
            var el = $(e.target);
            var new_comments = el.val();

            this.model.set("comments", new_comments, { silent: true });
        }

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

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

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

            this.model.set("batchId", new_batchId, { silent: true });
        }

        , save: function () {
            var that = this;
            var QP = new Core.Database.QueryParameters();
            var model = this.model; 
            QP.Add("DelayID", "INT", model.get("delayId"));
            QP.Add("Comments", "VARCHAR", model.get("comments"));

            var delayCodeId = document.getElementById("childDelaySelect").value; 
            delayCodeId = (delayCodeId != -1) ? delayCodeId : null;  
            QP.Add("DelayCodeID", "INT", delayCodeId);

            app.CallProcedure(app.DatabaseNames.MES + ".CAS.UpdateDelay", QP, {
                onSuccess: function (data) {
                    //if (data && data.Table && data.Table.length > 0) {
                    //    data = data.Table[0];
                    that.hide(); 
                    //}
                },
                Secured: true, 
            }, app.ConnectionStrings.app);
        }

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

            QP.Add("DelayID", "INT", model.get("delayId")); 

            var modal = new Modal.Views.Main({
                id: "remove-delay-confirmation-modal"
                , title: "Remove Delay"
                , message: "Are you sure you want to remove this delay?"
                , allowCancel: true
                , buttons_type: "CONTINUE-CANCEL"
            });

            modal.on("continue", function () {
                that.$el.show(); 

                app.CallProcedure(app.DatabaseNames.MES + ".CAS.RemoveDelay", QP, {
                    onSuccess: function (data) {
                        that.hide();
                    },
                    Secured: true,
                }, app.ConnectionStrings.app);
            });

            modal.on("cancel", function () {
                that.$el.show(); 
            });

            modal.on("shown", function () {
            }); 

            that.$el.hide();
            modal.show();
        }

        , splitDelay: function () {
            var that = this;
            var QP = new Core.Database.QueryParameters();
            var model = this.model;
            QP.Add("DelayID", "INT", model.get("delayId"));
            app.CallProcedure(app.DatabaseNames.MES + ".CAS.SplitDelay", QP, {
                onSuccess: function (data) {
                    that.hide();
                },
                Secured: true,
            }, app.ConnectionStrings.app);
        }

        , joinDelay: function () {
            var that = this;            
            
            CasterDelaysManager.Views.DelaySplitInformationModal.joinDelay(this.model.get("delayId"), function (data) {
                that.hide();
            }); 
        }

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

        , _startAutoRefresh: function () {
            try {
                if (this.options.MYREFERENCES.autoRefresh.toid != null) {
                    clearTimeout(this.options.MYREFERENCES.autoRefresh.toid);
                    this.options.MYREFERENCES.autoRefresh.toid = null;
                }

                this.options.MYREFERENCES.autoRefresh.enabled = true;

                this._autoRefresh();
            } catch (Error) { }
        }

        , _autoRefresh: function () {
            if (this.options.MYREFERENCES.autoRefresh.toid != null) {
                clearTimeout(this.options.MYREFERENCES.autoRefresh.toid);
                this.options.MYREFERENCES.autoRefresh.toid = null;
            }

            this.refresh();

            if (this.options.MYREFERENCES.autoRefresh.enabled == true) {
                this.options.MYREFERENCES.autoRefresh.toid = setTimeout(this._autoRefresh, 3000);
            }
        }

        , _stopAutoRefresh: function () {
            if (this.options.MYREFERENCES.autoRefresh.toid != null) {
                clearTimeout(this.options.MYREFERENCES.autoRefresh.toid);
                this.options.MYREFERENCES.autoRefresh.toid = null;
            }
            this.options.MYREFERENCES.autoRefresh.enabled = false;
        }
        , 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._stopAutoRefresh();
            this.remove();
            this.unbind();
        }

        , preRender: function () {
        }

        , reRender: function () {
        }

    
    });

    CasterDelaysManager.Views.DelaySplitInformationModal.joinDelay = function (id, callback) {
        var QP = new Core.Database.QueryParameters();

        QP.Add("Id", "INT", id);

        app.CallProcedure(app.DatabaseNames.MES + ".CAS.JoinDelay", QP, {
            onSuccess: function (data) {
                if (callback && _.isFunction(callback)) callback.call(this, data); 
            },
            Secured: true,
        }, app.ConnectionStrings.app);
    }; 

    CasterDelaysManager.Models.SplitDelay = Backbone.Model.extend({
        defaults: {
            id: null,
            start: null,
            end: null,
            duration: null, 

            //internals
            split1_duration: null,
            split2_duration: null, 
        },
    }); 

    CasterDelaysManager.Collections.NewDelay = Backbone.Collection.extend({
        setDataColl: function (data) {
            this.set(data);
        }
    });


    CasterDelaysManager.Views.SplitDelay = Backbone.View.extend({
        template: "caster-delays-manager"
        , id: "caster-delays-manager"
        , 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,
            };
            this.bus = this.options.bus;
            if (this.options.viewParams) {
                this.options.MYREFERENCES.rowData = this.options.viewParams.rowData;
            }

            this.newDelayCollection = new CasterDelaysManager.Collections.NewDelay();
            this.options._isRendered = false;
            this.options.sliders = {}; 

            this.bindEvents();
            _.bindAll(this);
        },




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

            var model = this.model;

            var s1duration = this.model.get("split1_duration");
            var s2duration = this.model.get("split2_duration");

            if (s1duration > 0 && s2duration > 0) {
                QP.Add("Id", "INT", model.get("id"));
                QP.Add("Seconds", "INT", model.get("split1_duration"));
                app.CallProcedure(app.DatabaseNames.MES + ".CAS.SplitDelayAt", QP, {
                    onSuccess: function (data) {
                        that.hide(data);
                    },
                    Secured: true,

                }, app.ConnectionStrings.app);
            }
        }
        , events: {
            'click .close, .btn-close': function (event) {
                event.preventDefault();

                this.trigger('cancel');

                if (this.options.content && this.options.content.trigger) {
                    this.options.content.trigger('cancel', this);
                }
            },
            "click #delay_split_modal_split_btn": "splitDelay",
            "click .slider-arrow-right": "slideRight",
            "click .slider-arrow-left": "slideLeft",
        },

        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/custom-screens/caster-delays-manager/";

            that.options._isRendered = true;
            
            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 startDate = that.model.get("start"); 
                    var endDate = that.model.get("end");

                    var ctx = {
                        start_date: startDate.format("YYYY-MM-DD"), 
                        end_date: endDate.format("YYYY-MM-DD"),
                        start_time: startDate.format("HH:mm:ss"),
                        end_time: endDate.format("HH:mm:ss"),
                    }; 

                    //loading the view and appeding it to the views's $el.
                    that.$el.html(tmp(ctx));

                    setTimeout(function () {
                         that.options.sliders.split = that.$el.find(".slider").slider({
                            formatter: function (value) {
                                var start = new Date(startDate.toDate().getTime() + (parseInt(value, 10) * 1000));
                                return "Split at: " + new moment(start).format("YYYY-MM-DD HH:mm:ss"); 
                            },
                            min: 0,
                            max: that.model.get("duration"),
                            step: 1,
                            value: parseInt(that.model.get("duration"))/2, 
                        }).data('slider');

                        that.$el.find(".slider").on("change", _.throttle(function (ev) {
                            that.updateModelSplitDurations();
                            that.$el.find(".slider-container .slider-selection").tooltip('show');
                            that.$el.find(".slider-container .slider-track-high").tooltip('show');
                        }, 100)); 

                        that.updateModelSplitDurations(); 

                        that.$el.find(".slider-container .slider-selection").tooltip({
                            title: function () {
                                var model = that.model;
                                return that.secondsToHHMMSS(model.get("split1_duration")); 
                            }, 
                            placement: "bottom",
                            trigger: "manual",
                            animation: false,
                            template: '<div class="tooltip gray-tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
                        }).tooltip("show");

                        that.$el.find(".slider-container .slider-track-high").tooltip({
                            title: function () {
                                var model = that.model;
                                return that.secondsToHHMMSS(model.get("split2_duration"));
                            },
                            placement: "bottom",
                            trigger: "manual",
                            animation: false,
                            template: '<div class="tooltip gray-tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
                        }).tooltip("show");

                    }, 500); 

                    that.options._isRendered = true;

                }, true, customPath);

            }, customPath, "delay_split_split_action_template");
        }

        , updateModelSplitDurations: function () {
            var val = this.options.sliders.split.getValue();
            var duration = this.model.get("duration");

            this.model.set({
                split1_duration: val,
                split2_duration: duration - val,
            });
        }

        , 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" : ""));
        }

        , slideRight: function () {
            var val = this.options.sliders.split.getValue();
            this.options.sliders.split.setValue(val + 1, true, true); 
        }
        , slideLeft: function () {
            var val = this.options.sliders.split.getValue();
            this.options.sliders.split.setValue(val - 1, true, true);
        }

        

        , refresh: function () {
            try {
            } catch (Error) { }
        }

        , checkSplitsLength: function () {
            var s1duration = this.model.get("split1_duration");
            var s2duration = this.model.get("split2_duration");
            var splitBtn = this.$el.find("#delay_split_modal_split_btn"); 

            if (s1duration > 0 && s2duration > 0) splitBtn.prop("disabled", false); 
            else splitBtn.prop("disabled", true);
        }

        , 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 (data) {
            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);
                }
                self.newDelay = data;
                if (self.options.content && self.options.content.trigger) {
                    self.options.content.trigger('hidden', self);
                }

                self.trigger('hidden');
                self.trigger('delaySplitted',data);

                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:split1_duration", this.checkSplitsLength);
            this.listenTo(this.model, "change:split2_duration", this.checkSplitsLength);
        }

        , close: function () {
            this.remove();
            this.unbind();
        }

        , preRender: function () {
        }

        , reRender: function () {
        }
    });

    CasterDelaysManager.Models.SubnavBarControls = Backbone.Epoxy.Model.extend({
        defaults: {
            from: null,
            to: null,

            crewId: -1,
            lineProductionItemId: -1,
            operatingUnitId: -1,
            productId: -1,
            shiftId: -1,
            delayCategoryId: -1,
            causeId: -1,
            areaId: -1,

            lines: [],
            machinesInternal: [],
            products: [],
            shifts: [
                { value: 1, label: 'D' },
                { value: 2, label: 'N' },
            ],
            delayCategories: [],
            operatingUnits: [],
            causes: [],
            areas: [],
            crews: [
                { value: "1", label: "A" },
                { value: "2", label: "B" },
                { value: "3", label: "C" },
                { value: "4", label: "D" }
            ],

        },
        initialize: function () {
            var toDate = new Date(); 
            var fromDate = new Date(toDate);
            fromDate.setDate(toDate.getDate() - 7); 
           
            this.set({
                from: new moment(fromDate).format("YYYY-MM-DD"),
                to: new moment(toDate).format("YYYY-MM-DD"),
            }, { silent: true });

            this.fetchDelayCategories();
        },
       
        fetchDelayCategories: function () {
            var that = this;
            Core.Json.CallProcedure(app.DatabaseNames.MES + ".CAS.GetDelayCodes", null, {
                onSuccess: function (data) {
                    if (data && data.Table) {
                        var items = data.Table;

                        that.set({
                            delayCategories: _.map(items, function (m) {
                                return { id: m.Id, parentId: m.ParentId, text: m.Name, rootId: m.RootParentId };
                            }),
                        });

                        that.set({
                            operatingUnits: _.map(data.Table1, function (m) {
                                return { value: m.Id, label: m.Name, };
                            }),
                        });

                        that.set({
                            causes: _.map(data.Table2, function (m) {
                                return { value: m.Id, label: m.Name, };
                            }),
                        });

                        that.set({
                            areas: _.map(data.Table3, function (m) {
                                return { value: m.Id, label: m.Name, };
                            }),
                        });
                    }
                },
                Async: true,
                Secured: true,
            }, app.ConnectionStrings.app);
        },
    }); 

    //subview for the subnavbar controls
    CasterDelaysManager.Views.SubnavBarControls = Backbone.Epoxy.View.extend({
        id: "caster-delays-manager-subnavbar-controls"
        , title: ""
        , template: "caster-delays-manager"
        , initialize: function () {
            this.options.state = app.view_states.loading;
            this.options.onappend = (_.isFunction(this.options.onappend)) ? this.options.onappend : function () { };

            if (this.options.viewParams) {
            }

            this.options.MYREFERENCES = {};

            this.options.viewModels = {
                fromDateControl: new DateControl.Model({
                    date: this.model.get("from"), 
                }),
                toDateControl: new DateControl.Model({
                    date: this.model.get("to"),
                }), 
            };            

            this.bindEvents();
            //_.bindAll(this);
        },

        events: {
            "click .btn-export-to-excel": 'exportToExcel',
        },

        render: function (container, onComplete) {
            var that = this;
            var thatContainer = (container) ? container : (this.options.container) ? this.options.container : null;
            var onViewComplete = (onComplete) ? onComplete : function () { };

            //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/custom-screens/caster-delays-manager/";

            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;

                    //loading the view and appeding it to the views's $el.
                    that.$el.html(tmp());
                    that.applyBindings();

                    var dc = new DateControl.Views.Main({
                        model: that.options.viewModels.fromDateControl,
                    });
                    dc.render(that.$el.find(".from-date-control-container"));

                    var dc = new DateControl.Views.Main({ model: that.options.viewModels.toDateControl });
                    dc.render(that.$el.find(".to-date-control-container"));

                    that.append(thatContainer, that.$el);
                }, true, customPath);
            }, customPath, "subnavbar_controls");
        }

        , append: function (container, el) {
            el = (el != null && el != undefined) ? el : this.$el;

            if (this.options.state == app.view_states.loading
                || this.options.state == app.view_states.shown) {
                //appending view to the main container and set state to shown

                this.options.state = app.view_states.shown;
                container.append(el);

                this.options.onappend(this);
            }

            if (this.options.state == app.view_states.hidden) {
                //append and remain hidden
                container.append(el);
            }

            if (this.options.state == app.view_states.closed) {
                //return without appending.
                return;
            }
        }

        , setExportButtonExporting: function (val) {
            var btn_export = this.$el.find('.btn-export-to-excel');
            var export_state = btn_export.find('.excel-export-state');
            var loading_state = btn_export.find('.loading-state');

            if (val) {
                export_state.css('display', 'none', 'important');
                loading_state.removeClass('hide');

                btn_export.attr('disabled', true);
            } else {
                loading_state.addClass('hide');
                export_state.css('display', 'inline-block', 'important');

                btn_export.attr('disabled', false);
            }
        }

        , exportToExcel: function () {
            if (_.isFunction(this.options.onExportToExcel)) {
                this.options.onExportToExcel.call(this);
            }
        }

        , refresh: function () {
            try {

            } catch (Error) { }
        }

        , 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

            this.listenTo(this.options.viewModels.fromDateControl, "change:date", this.fromToModelChanged);
            this.listenTo(this.options.viewModels.toDateControl, "change:date", this.fromToModelChanged);
        }

        , fromToModelChanged: function (a, b, c) {
            this.model.set({
                from: this.options.viewModels.fromDateControl.get("date"),
                to: this.options.viewModels.toDateControl.get("date"),
            }); 
        }

        , close: function () {
            this.options.state = app.view_states.closed;

            this.remove();
            this.unbind();
        }

        , show: function () {
            this.options.state = app.view_states.shown;

            this.bindEvents();
            this.$el.show();
        }

        , hide: function () {
            this.options.state = app.view_states.hidden;

            this.$el.hide();
            this.unbind();
            this.stopListening();
        }

        , reRender: function () {
        }
    });


    CasterDelaysManager.Views.Select = Backbone.Epoxy.View.extend({
        el: null,
        data: null,
        maximumSelectionLength: null,
        selectType: 'default', // default, tree

        initialize: function (opt) {
            this.el = opt.el;
            this.data = opt.data;
            this.maximumSelectionLength = opt.maximumSelectionLength ? opt.maximumSelectionLength : null;
            this.selectType = opt.selectType ? opt.selectType : 'default';

            this.render();
        },
        render: function () {
            var that = this;
            if (that.maximumSelectionLength) this.$el.attr("multiple", true);

            if (this.selectType === 'tree') {
                this.$el.select2ToTree({
                    treeData: {
                        dataArr: that.data,
                    },
                    expandSelectedItemParents: true,
                    maximumSelectionLength: that.maximumSelectionLength,

                });
                this.$el.select2ToTree({ expandSelectedItemParents: true });
                //this.$el.prop('disabled', true).trigger('change');
            } else {
                this.$el.select2({
                    data: that.data
                });
                this.$el.prop('disabled', true).trigger('change');
            }
        },
    })
    // Required, return the module for AMD compliance.
    return CasterDelaysManager;

});

