//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',
    'moment',

    'components/ag-grid/ag-grid-module',
    'modules/modal2',
    'modules/modal-sulpher-print/modal-sulpher-print',
],
    function (app, T, moment, AgGridModule, Modal, SulpherPrintModal) {

        var Screen = { Models: {}, Views: {}, Collections: {} }

        Screen.Models.Main = Backbone.Epoxy.Model.extend({
            defaults: {
                start: new moment().subtract(2, 'days').format('YYYY-MM-DD'),
                end: new moment().format('YYYY-MM-DD'),

                casterCode: 1,
                casters: [{ label: 'All', value: null }, { label: '1', value: 1 }, { label: '2', value: 2 }],

                crewId: null,
                crews: [{ label: 'A', value: 'A' }, { label: 'B', value: 'B' }, { label: 'C', value: 'C' }, { label: 'D', value: 'D' }],

                shiftId: null,
                shifts: [{ label: 'D', value: 1 }, { label: 'N', value: 2 }],

                strandId: null,

                hasData: false,
                isLoading: false,
                searchText: '',
                isPageLoading: false,
            },
            computeds: {
                strands: {
                    deps: ['casterCode'],
                    get: function (casterCode) {
                        var value = parseInt(casterCode);
                        if (value === 1) return [{ label: '1', value: 1 }, { label: '2', value: 2 }, { label: '3', value: 3 }, { label: '4', value: 4 }];
                        else if (value === 2) return [{ label: '5', value: 5 }, { label: '6', value: 6 }, { label: '8', value: 8 }, { label: '9', value: 9 }];
                        else return [{ label: '1', value: 1 }, { label: '2', value: 2 }, { label: '3', value: 3 }, { label: '4', value: 4 }, { label: '5', value: 5 }, { label: '6', value: 6 }, { label: '8', value: 8 }, { label: '9', value: 9 }];
                    },
                },
                start$: {
                    deps: ['start'],
                    get: function (value) {
                        return value;
                    },
                    set: function (value) {
                        return { start: (value) ? new moment(value, app.translate(app, 'MM/DD/YYYY')).format('YYYY-MM-DD') : value, };
                    },
                },
                end$: {
                    deps: ['end'],
                    get: function (value) {
                        return value;
                    },
                    set: function (value) {
                        return { end: (value) ? new moment(value, app.translate(app, 'MM/DD/YYYY')).format('YYYY-MM-DD') : value, };
                    },
                },
            },
            printTag: function (params) {
                var that = this,
                    qp = new Core.Database.QueryParameters();

                this.fixedParameters = [
                    { Name: '@productId', Type: 'INT', Value: params.productId, },
                    { Name: '@Printer', Type: 'INT', Value: params.printer, },
                    { Name: '@ReasonPhraseId', Type: 'INT', Value: params.reasonPhraseId, },
                    { Name: '@Comments', Type: 'VARCHAR', Value: params.comments, },
                    { Name: '@Employee', Type: 'VARCHAR', Value: params.employee, },
                    { Name: '@IsColdLength', Type: 'INT', Value: (params.isColdLength === 1 ? 1 : 0) }
                ];
                _.each(this.fixedParameters, function (qpParams) {
                    qp.Add(qpParams.Name, qpParams.Type, qpParams.Value);
                });
                Core.Json.CallProcedure(
                    app.DatabaseNames.MES + '.CAS.UpsertTaggingCommand',
                    qp,
                    {
                        onSuccess: function (resp) {
                            try {
                                if ((resp) && (resp.Table)) {
                                    app.views.topMessages.showMessage('Tagging in process...', { stay: 5000, });
                                    that.trigger('triggerFetch');
                                }
                                else {
                                    if ((resp) && (resp.Message)) {
                                        console.error(new Error(resp.Message).stack);
                                        app.views.topMessages.showMessage('CALL TO DATABASE FAILED', { stay: 5000, });
                                    }
                                    else {
                                        app.views.topMessages.showMessage('SERVER RESPONSE NOT VALID', { stay: 5000, });
                                        console.error(new Error('SERVER_RESPONSE_NOT_VALID').stack);
                                    }
                                }
                            }
                            catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                        },
                        onFailure: function (resp) {
                            console.error(resp);
                        },
                        Secured: true,
                        Async: true,
                    },
                    app.ConnectionStrings.app
                );
                return this;
            },
            resendToL3: function (params) {
                var that = this,
                    qp = new Core.Database.QueryParameters();
                this.fixedParameters = [
                    { Name: '@productId', Type: 'INT', Value: params.productId, },
                ];
                _.each(this.fixedParameters, function (qpParams) {
                    qp.Add(qpParams.Name, qpParams.Type, qpParams.Value);
                });

                Core.Json.CallProcedure(
                    app.DatabaseNames.MES + '.CAS.ResendProductToL3',
                    qp,
                    {
                        onSuccess: function (resp) {
                            try {
                                if ((resp) && !(resp.Message)) {
                                    app.views.topMessages.showMessage('Resend Product to L3 in process...', { stay: 5000, });
                                    that.trigger('triggerFetch');
                                }
                                else {
                                    if ((resp) && (resp.Message)) {
                                        console.error(new Error(resp.Message).stack);
                                        app.views.topMessages.showMessage('CALL TO DATABASE FAILED', { stay: 5000, });
                                    }
                                    else {
                                        app.views.topMessages.showMessage('SERVER RESPONSE NOT VALID', { stay: 5000, });
                                        console.error(new Error('SERVER_RESPONSE_NOT_VALID').stack);
                                    }
                                }
                            }
                            catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                        },
                        onFailure: function (resp) {
                            console.error(resp);
                        },
                        Secured: true,
                        Async: true,
                    },
                    app.ConnectionStrings.app
                );
                return this;
            },
        });

        Screen.Collections.Items = Backbone.Collection.extend({
            isFetching: false,

            fixedParameters: [],

            fetch: function (params) {
                var that = this,
                    qp = new Core.Database.QueryParameters(),
                    options = params ? _.clone(params) : {};

                this.isFetching = true;
                this.fixedParameters = [
                    { Name: '@Start', Type: 'DATETIME', Value: params.start, },
                    { Name: '@End', Type: 'DATETIME', Value: params.end, },
                    { Name: '@CrewId', Type: 'CHAR', Value: params.crewId != '-' ? params.crewId : null, },
                    { Name: '@ShiftId', Type: 'INT', Value: params.shiftId != '-' ? params.shiftId : null, },
                    { Name: '@StrandId', Type: 'INT', Value: params.strandId != '-' ? params.strandId : null, },
                    { Name: '@TimeZoneCode', Type: 'CHAR', Value: app.models.user.get('timezoneCode'), },
                    { Name: '@casterCode', Type: 'INT', Value: params.casterCode, },
                    { Name: '@SearchText', Type: 'VARCHAR', Value: params.searchText != '' ? params.searchText : null, },
                ];

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

                // Load all data at once - ag-grid handles client-side pagination
                qp.Add('@fromRow', 'INT', 0);
                qp.Add('@rowsToFetch', 'INT', 100000);

                Core.Json.CallProcedure(
                    app.DatabaseNames.MES + '.CAS.GetProducts',
                    qp,
                    {
                        onSuccess: function (resp) {
                            try {
                                if ((resp) && (resp.Table)) {
                                    var newColl = resp.Table;
                                    that.set(newColl);
                                    that.trigger('fetch', that, newColl);
                                    that.isFetching = false;
                                }
                                else {
                                    if ((resp) && (resp.Message)) {
                                        console.error(new Error(resp.Message).stack);
                                        app.views.topMessages.showMessage('CALL TO DATABASE FAILED', { stay: 5000, });
                                    }
                                    else {
                                        app.views.topMessages.showMessage('SERVER RESPONSE NOT VALID', { stay: 5000, });
                                        console.error(new Error('SERVER_RESPONSE_NOT_VALID').stack);
                                    }
                                    that.isFetching = false;
                                }
                            }
                            catch (e) {
                                console.error((e.stack) ? e.stack : new Error(e).stack);
                                that.isFetching = false;
                            }
                        },
                        onFailure: function (resp) {
                            console.error(resp);
                            that.isFetching = false;
                        },
                        Secured: true,
                        Async: true,
                    },
                    app.ConnectionStrings.app
                );
                return this;
            },
        });


        //-------------------------------//
        //------ AG-Grid Module ---------//
        //-------------------------------//
        var CustomAgGridModule = AgGridModule.extend({
            initialize: function (options) {
                this.bus = options.bus;
                this.itemsColl = options.itemsColl;
                this.columnDefs = [
                    { field: 'ProductNumber', headerName: 'Product Number', flex: 1.5, showFilter: true, cellClass: 'text-center', headerClass: 'text-center' },
                    {
                        field: 'hasSulfur',
                        headerName: 'Sulfur Assigned',
                        flex: 0.8,
                        showFilter: true,
                        cellClass: 'text-center',
                        headerClass: 'text-center',
                        cellStyle: function (params) {
                            if (params.value === 'Yes') {
                                return { backgroundColor: '#b3ffb3', textAlign: 'center' };
                            } else if (params.value === 'No') {
                                return { backgroundColor: '#ff9999', textAlign: 'center' };
                            }
                            return { textAlign: 'center' };
                        }
                    },
                    { field: 'CutStart', headerName: 'Cut Time', flex: 1.2, fieldType: 'Datetime', format: 'MM/DD/YYYY HH:mm', cellClass: 'text-center', headerClass: 'text-center' },
                    { field: 'CasterCode', headerName: 'Caster', flex: 0.6, cellClass: 'text-center', headerClass: 'text-center' },
                    { field: 'StrandId', headerName: 'Strand', flex: 0.6, cellClass: 'text-center', headerClass: 'text-center' },
                    { field: 'Sequence', headerName: 'Sequence', flex: 0.6, cellClass: 'text-center', headerClass: 'text-center' },
                    { field: 'CrewId', headerName: 'Crew', flex: 0.5, cellClass: 'text-center', headerClass: 'text-center' },
                    { field: 'Shift', headerName: 'Shift', flex: 0.5, cellClass: 'text-center', headerClass: 'text-center' },
                    { field: 'Weight', headerName: 'Weight', flex: 0.8, cellClass: 'text-center', headerClass: 'text-center' },
                    { field: 'Length', headerName: 'Length', flex: 0.8, fieldType: 'Float', decimals: 2, cellClass: 'text-center', headerClass: 'text-center' },
                    { field: 'MetLengthStart', headerName: 'Met Length Start', flex: 0.9, fieldType: 'Float', decimals: 2, cellClass: 'text-center', headerClass: 'text-center' },
                    { field: 'MetLengthEnd', headerName: 'Met Length End', flex: 0.9, fieldType: 'Float', decimals: 2, cellClass: 'text-center', headerClass: 'text-center' },
                    { field: 'SentToL3', headerName: 'Sent To L3', flex: 0.7, showFilter: true, cellClass: 'text-center', headerClass: 'text-center' },
                ];

                options.columnDefs = this.columnDefs;

                AgGridModule.prototype.initialize.call(this, options);
            },
            getContextMenuItems: function (params) {
                var self = this;
                return [
                    {
                        name: 'Send To L3',
                        icon: '<i class="fa fa-share-square"></i>',
                        action: function () {
                            if (params.node && params.node.data) {
                                self.bus.trigger('contextAction', 'opt-send-to-l3', params.node.data);
                            }
                        }
                    },
                    'separator',
                    {
                        name: 'Print Tag',
                        icon: '<i class="fa fa-tag"></i>',
                        action: function () {
                            if (params.node && params.node.data) {
                                self.bus.trigger('contextAction', 'opt-print-tag', params.node.data);
                            }
                        }
                    },
                    'separator',
                    {
                        name: 'Edit Sulfur Rating',
                        icon: '<i class="fa fa-pencil"></i>',
                        action: function () {
                            if (params.node && params.node.data) {
                                self.bus.trigger('contextAction', 'sulfur-print-rating', params.node.data);
                            }
                        }
                    },
                    'separator',
                    {
                        name: 'Edit Length',
                        icon: '<i class="fa fa-pencil"></i>',
                        action: function () {
                            if (params.node && params.node.data) {
                                self.bus.trigger('contextAction', 'opt-edit-length', params.node.data);
                            }
                        }
                    },
                    'separator',
                    'copy',
                    {
                        name: 'Copy Selected with Headers',
                        action: function () {
                            self.copySelectedToClipboard(true);
                        }
                    },
                    'separator',
                    {
                        name: 'Export All to Excel',
                        action: function () {
                            self.exportToExcel(false);
                        }
                    },
                    {
                        name: 'Export Selected to Excel',
                        action: function () {
                            self.exportToExcel(true);
                        }
                    }
                ];
            },
            onCellClicked: function (params) {
                AgGridModule.prototype.onCellClicked.call(this, params);
            }
        });


        //-------------------------------//
        //------ Main View -------------//
        //-------------------------------//
        Screen.Views.Main = Backbone.Epoxy.View.extend({
            template: 'caster-products',
            id: 'caster-products',
            title: 'Caster Products',
            events: function () {
                return {
                    'click #refreshBtn': this.refreshBtn_click,
                    'click #calendarStartBtn': this.calendarStartBtn_click,
                    'click #calendarEndBtn': this.calendarEndBtn_click,
                    'keypress #search': this.search_keypress,
                };
            },
            bindings: 'data-bind',
            bindingSources: null,
            grids: null,
            itemsColl: null,
            subviews: null,
            viewParams: null,

            initialize: function () {
                this.options.state = app.view_states.loading;
                this.options.onappend = (_.isFunction(this.options.onappend)) ? this.options.onappend : function () { };

                var that = this;

                if (!this.model)
                    this.model = new Screen.Models.Main();

                this.bus = _.extend({}, Backbone.Events);

                this.agGridModule = new CustomAgGridModule({
                    itemsColl: this.itemsColl,
                    bus: this.bus,
                    rowData: [],
                    onChange: this.handleGridChange.bind(this),
                    onRemove: this.handleGridRemove.bind(this),
                    fileName: 'caster-products',
                    screenTitle: 'Caster Products',
                    isPageLoading: that.model.get('isPageLoading'),
                });

                this.grids = {};
                this.itemsColl = new Screen.Collections.Items();
                this.bindingSources = {};
                this.subviews = {};

                this.bindEvents();
            },
            handleGridChange: function (event) { },
            handleGridRemove: function () { },
            calendarStartBtn_click: function () {
                $('#dateStartTbx').datepicker('show');
            },
            calendarEndBtn_click: function () {
                $('#dateEndTbx').datepicker('show');
            },
            bindEvents: function () {
                this.listenTo(this.itemsColl, 'fetch', this.processes_ready)
                    .listenTo(this.model, 'triggerFetch', this.refreshBtn_click);

                this.listenTo(this.bus, 'modalAcceptBtn', this.onModalAcceptBtn);
                this.listenTo(this.bus, 'contextAction', this.handleContextAction);
            },
            onModalAcceptBtn: function () {
                this.refreshBtn_click();
            },
            handleContextAction: function (action, rowData) {
                var that = this;

                switch (action) {
                    case 'opt-send-to-l3':
                        var message = 'The product ' + rowData.ProductNumber + ' will be sent to L3. Do you want to continue?';
                        var modal = new Modal.Views.Main({
                            focusOk: false,
                            focusSelector: '#btn-cancel',
                            title: app.translate([this, app], "resend_item_modal_confirm_title"),
                            message: message,
                            buttons_type: "CONTINUE-CANCEL",
                        });
                        this.listenToOnce(modal, "continue", function (modal) {
                            try {
                                that.model.resendToL3({
                                    productId: rowData.Id
                                });
                            }
                            catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                        });
                        modal.show();
                        break;

                    case 'opt-print-tag':
                        var printModal = new Screen.Views.PrintTagConfirmationModal({
                            data: rowData,
                            bus: this.bus
                        });
                        printModal.show();
                        break;

                    case 'sulfur-print-rating':
                        var data = {
                            ProductNumber: rowData.ProductNumber,
                            HeatNumber: rowData.HeatName,
                            Strand: rowData.StrandId,
                            Cut: rowData.Sequence,
                            Date: rowData.CutStart,
                            Grade: rowData.GradeName,
                            ProductId: rowData.Id
                        };
                        var sulfurModal = new SulpherPrintModal.Views.SulfurPrintRatings({
                            parent: this,
                            data: data,
                            rowModel: rowData,
                            bus: that.bus,
                        });
                        sulfurModal.show();
                        break;

                    case 'opt-edit-length':
                        var editModal = new Screen.Views.EditLengthModal({
                            data: rowData,
                            bus: this.bus
                        });
                        editModal.show();
                        break;
                }
            },
            _refresh: function (opt) {
                this.itemsColl.reset();
                this.model.set({
                    hasData: false,
                });

                this.refreshProcesses(opt);
            },
            refresh: function (viewParams) {
                var fixedParams = _.extend({}, Screen.Models.Main.prototype.defaults, viewParams);

                if (viewParams.start)
                    fixedParams.start = new moment(fixedParams.start, 'YYYYMMDD').format('YYYY-MM-DD');
                if (viewParams.end)
                    fixedParams.end = new moment(fixedParams.end, 'YYYYMMDD').format('YYYY-MM-DD');
                if (viewParams.casterCode)
                    fixedParams.casterCode = (viewParams.casterCode != '-' && viewParams.casterCode != null) ? parseInt(viewParams.casterCode, 10) : null;
                if (viewParams.crewId)
                    fixedParams.crewId = (viewParams.crewId != '-' && viewParams.crewId != null) ? viewParams.crewId : null;
                if (viewParams.shiftId)
                    fixedParams.shiftId = (viewParams.shiftId != '-' && viewParams.shiftId != null) ? parseInt(viewParams.shiftId, 10) : null;
                if (viewParams.strandId)
                    fixedParams.strandId = (viewParams.strandId != '-' && viewParams.strandId != null) ? parseInt(viewParams.strandId, 10) : null;

                this.model.set(fixedParams);

                this._refresh({
                    refresh: true
                });
            },
            refreshProcesses: function (options) {
                var that = this,
                    attrs = this.model.toJSON(),
                    opt = _.extend({}, options, { params: {}, });

                if ((opt.refresh == true) || (opt.reset == true)) {
                    this.model.set('isLoading', true);
                    that.agGridModule.showLoadingOverlay();
                }

                this.itemsColl.fetch({
                    start: attrs.start,
                    end: attrs.end,
                    crewId: (attrs.crewId == "") ? null : attrs.crewId,
                    shiftId: (attrs.shiftId == "") ? null : attrs.shiftId,
                    strandId: (attrs.strandId == "") ? null : attrs.strandId,
                    casterCode: attrs.casterCode === "1" || attrs.casterCode === "2" ? attrs.casterCode : null,
                    searchText: attrs.searchText,
                    refresh: true,
                });
            },
            processes_ready: function (collection, data) {
                var that = this;
                try {
                    var collectionData = that.itemsColl;
                    setTimeout(
                        function () {
                            that.agGridModule.setRowDataAsCollection(collectionData);
                            that.agGridModule.hideOverlay();
                            that.model.set({
                                hasData: (that.itemsColl.length > 0),
                                isLoading: false,
                            });
                        },
                        100
                    );
                }
                catch (e) {
                    console.error((e.stack) ? e.stack : new Error(e).stack);
                    this.model.set({ isLoading: false });
                    if (that.agGridModule && that.agGridModule.hideOverlay) {
                        that.agGridModule.hideOverlay();
                    }
                }
            },
            search_keypress: function (e) {
                if (e.keyCode === 13) {
                    $('#search').blur();
                    this.refreshBtn_click();
                }
            },
            refreshBtn_click: function (e) {
                try {
                    var params = this.model.toJSON();
                    app.router.navigate(
                        app.router.resolveURL(
                            app.router.currentModule,
                            _.extend(
                                {},
                                params,
                                {
                                    start: new moment(params.start, 'YYYY-MM-DD').format('YYYYMMDD'),
                                    end: new moment(params.end, 'YYYY-MM-DD').format('YYYYMMDD'),
                                    casterCode: (params.casterCode == null || params.casterCode == "") ? '-' : params.casterCode,
                                    crewId: (params.crewId == null || params.crewId == "") ? '-' : params.crewId,
                                    shiftId: (params.shiftId == null || params.shiftId == "") ? '-' : params.shiftId,
                                    strandId: (params.strandId == null || params.strandId == "") ? '-' : params.strandId,
                                }
                            ),
                            false
                        ),
                        { trigger: false, }
                    );

                    this._refresh({
                        reset: true,
                    });

                    window.scrollTo(0, 0);
                }
                catch (Error) { console.error(Error.stack); }
            },
            render: function (container, viewParams) {
                var that = this;

                this.viewParams = viewParams;

                that.model.set({ isPageLoading: true });

                var thatContainer = (this.options.container) ? this.options.container : container;
                this.options.container = thatContainer;

                var customPath = '/app/pages/caster/caster-products/';

                T.render.call(
                    this,
                    this.template,
                    function (tmp) {
                        if (!that.options.i18n) that.options.i18n = {};

                        app.getI18NJed(
                            that,
                            that.template,
                            function (i18nJED) {
                                that.options.i18n[that.template] = i18nJED;

                                that.$el.html(tmp());

                                that.applyBindings();

                                that.$el.find('.input-date').datepicker();

                                // Render the AgGridModule and append it to the container
                                that.agGridModule.render();
                                that.$el.find('.processes-grid-container').append(that.agGridModule.$el);

                                //appending view to the main container
                                that.append(thatContainer, that.$el);

                                //Set model with view params here to prevent changes on the model when the view bindings are applied.
                                var fixedParams = _.extend({}, viewParams);

                                if (fixedParams.start)
                                    fixedParams.start = new moment(fixedParams.start, 'YYYYMMDD').format('YYYY-MM-DD');
                                if (fixedParams.end)
                                    fixedParams.end = new moment(fixedParams.end, 'YYYYMMDD').format('YYYY-MM-DD');
                                if (viewParams.casterCode)
                                    fixedParams.casterCode = (viewParams.casterCode != '-' && viewParams.casterCode != null) ? parseInt(viewParams.casterCode, 10) : null;
                                if (viewParams.crewId)
                                    fixedParams.crewId = (viewParams.crewId != '-' && viewParams.crewId != null) ? viewParams.crewId : null;
                                if (viewParams.shiftId)
                                    fixedParams.shiftId = (viewParams.shiftId != '-' && viewParams.shiftId != null) ? parseInt(viewParams.shiftId, 10) : null;
                                if (viewParams.strandId)
                                    fixedParams.strandId = (viewParams.strandId != '-' && viewParams.strandId != null) ? parseInt(viewParams.strandId, 10) : null;

                                that.model.set(fixedParams);

                                that.model.set({ isPageLoading: false });

                                // Initial load
                                that.refreshProcesses({ refresh: true });
                            },
                            true,
                            customPath
                        );
                    },
                    customPath
                );
            },

            //Common functions
            append: function (container, el) {
                el = el || this.$el;

                if (this.options.state == app.view_states.loading || this.options.state == app.view_states.shown) {
                    this.options.state = app.view_states.shown;
                    container.append(el);
                    this.options.onappend(this);
                } else if (this.options.state == app.view_states.hidden) {
                    container.append(el);
                } else if (this.options.state == app.view_states.closed) {
                    return;
                }
            },
            onRemove: function () {
                if (this.agGridModule) {
                    this.agGridModule.destroy();
                }
            },
            bindViewScopedEvents: function () { },
            unbindViewScopedEvents: function () { },
            close: function () {
                this.options.state = app.view_states.closed;
                this.closeSubviews();
                this.remove();
                this.unbindViewScopedEvents();
                this.unbind();
            },
            closeSubviews: function () {
                _.each(this.subviews, function (sview) {
                    sview.close();
                });
            },
            show: function () {
                this.options.state = app.view_states.shown;
                this.showSubviews();
                this.bindEvents();
                this.$el.show();
            },
            showSubviews: function () {
                _.each(this.subviews, function (sview) {
                    sview.show();
                });
            },
            hide: function () {
                this.options.state = app.view_states.hidden;
                this.hideSubviews();
                this.$el.hide();
                this.unbind();
                this.stopListening();
            },
            hideSubviews: function () {
                _.each(this.subviews, function (sview) {
                    sview.hide();
                });
            },
            preRender: function () {
                app.models.subnavbar.set("subnavbar", false);
            },
            reRender: function (viewParams) {
                try {
                    this.refresh(viewParams);
                } catch (Error) { }
            },
        });


        //-------------------------------//
        //------ Print Tag Confirmation -//
        //-------------------------------//
        Screen.Models.PrintTagConfirmation = Backbone.Epoxy.Model.extend({
            defaults: {
                productNumber: null,
                printerId: 1,
                comments: '',
                rowModel: null,
                printers: [{ value: 1, label: 1 }, { value: 2, label: 2 }],
                reasonPhrases: null,
                employeeNumber: null,
                reasonPhraseId: 1,
                pieceLength: 0,
                printLengthMode: 'cold',
                coldConversionFactor: 1.012
            },
            initialize: function () {
                var reasonPhrases = this.fetchReasonPhrases();
                this.set('reasonPhrases', reasonPhrases);
            },
            fetchReasonPhrases: function () {
                var reasonPhrases = [];
                var qp = new Core.Database.QueryParameters();
                Core.Json.CallProcedure(
                    app.DatabaseNames.MES + '.CAS.GetTagPrintReasonPhrases',
                    qp,
                    {
                        onSuccess: function (resp) {
                            try {
                                if (resp.Table) {
                                    reasonPhrases = resp.Table.map(function (item) {
                                        return {
                                            value: item.ReasonPhraseId,
                                            label: item.Name
                                        };
                                    });
                                }
                                else {
                                    if ((resp) && (resp.Message)) {
                                        app.views.topMessages.showMessage(resp.Message, { stay: 5000, });
                                        console.error(resp.Message);
                                    }
                                    else {
                                        app.views.topMessages.showMessage("Server response not valid.", { stay: 5000, });
                                        console.error("Server response not valid.");
                                    }
                                }
                            }
                            catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                        },
                        Async: false,
                        Secured: true,
                    },
                    app.ConnectionStrings.app
                );
                return reasonPhrases;
            }
        });

        Screen.Views.PrintTagConfirmationModal = Backbone.Epoxy.View.extend({
            template: "caster-products",
            id: "print-tag-confirmation",
            className: "modal modal-print-tag-confirmation hide fade",
            bindings: "data-bind",
            isCacheable: true,
            events: function () {
                return {
                    "click #acceptBtn": this.acceptBtn_click,
                    "click #cancelBtn": this.cancelBtn_click,
                    "submit form": this.form_submit,
                    "keypress": this.modal_keypress,
                    "show.bs.modal": this.modal_show,
                    "shown.bs.modal": this.modal_shown,
                    "hidden.bs.modal": this.modal_hidden,
                    "click #printLengthToggle label": "onPrintLengthToggleClick",
                    "change input[name='printLengthModeModal']": "onPrintLengthModeChange"
                };
            },
            container: null,
            disposed: false,
            isRendered: false,
            preventDispose: false,
            visible: false,
            data: null,
            productId: null,

            initialize: function (options) {
                _.extend(this, options);
                if (!this.model) {
                    this.model = new Screen.Models.PrintTagConfirmation();
                }
                var data = options.data;
                this.model.set({
                    productNumber: data.ProductNumber,
                    productId: data.Id,
                    pieceLength: data.Length,
                    originalPieceLength: data.Length
                });
                this.bus = options.bus;
                this.bindEvents();
                return this;
            },

            hide: function (preventDispose) {
                this.preventDispose = (preventDispose);
                this.$el.modal('hide');
            },
            render: function (container) {
                if (container)
                    this.container = container;

                var that = this;
                var customPath = '/app/pages/caster/caster-products/';
                T.render.call(this, this.template, function (tmp) {
                    if (!that.i18n) that.i18n = {};
                    app.getI18NJed(that, that.template, function (i18nJED) {
                        that.i18n[that.template] = i18nJED;
                        that.$el.html(tmp(that.model.toJSON()));
                        that.applyBindings();
                        that.isRendered = true;
                        that.trigger("render");
                    }, true, customPath);
                }, customPath, "print_confirmation_modal");
            },

            show: function () {
                if (!this.isRendered) {
                    this.render();
                }
                else {
                    this.$el.modal({
                        keyboard: true,
                        backdrop: 'both',
                    });
                }
                return this;
            },

            bindEvents: function () {
                this.listenToOnce(this, "render", this.view_render);
                this.listenTo(this.model, "change:pieceLength", this.updateColdLength);
            },

            close: function () {
                if (this.disposed == false) {
                    if (this.visible == true) {
                        this.hide();
                    }
                    else {
                        this.trigger('close');
                        this.remove();
                        this.unbind();
                        this.disposed = true;
                    }
                }
            },
            preRender: function () {
                app.models.subnavbar.set("dateControl", false);
            },
            reRender: function () { },

            acceptBtn_click: function (e) {
                try {
                    var that = this;
                    var model = this.model.toJSON();
                    var warningMessage = document.getElementById('warning');

                    if (model.employeeNumber === null) {
                        warningMessage.style.display = 'inline';
                        e.preventDefault();
                        return;
                    } else {
                        warningMessage.style.display = 'none';
                    }

                    var selectedLength;
                    if (model.printLengthMode === 'cold') {
                        selectedLength = (parseFloat(model.pieceLength) / parseFloat(model.coldConversionFactor));
                    } else {
                        selectedLength = parseFloat(model.pieceLength);
                    }
                    selectedLength = Math.round(selectedLength * 100) / 100;

                    var isColdLength = (model.printLengthMode === 'cold') ? 1 : 0;
                    this.printTag({
                        productId: model.productId,
                        printer: model.printerId,
                        employee: model.employeeNumber,
                        reasonPhraseId: model.reasonPhraseId,
                        comments: model.comments,
                        pieceLength: model.pieceLength,
                        isColdLength: isColdLength
                    });

                    this.close();
                }
                catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
            },

            printTag: function (params) {
                var that = this,
                    qp = new Core.Database.QueryParameters();

                this.fixedParameters = [
                    { Name: '@productId', Type: 'INT', Value: params.productId, },
                    { Name: '@Printer', Type: 'INT', Value: params.printer, },
                    { Name: '@ReasonPhraseId', Type: 'INT', Value: params.reasonPhraseId, },
                    { Name: '@Comments', Type: 'VARCHAR', Value: params.comments, },
                    { Name: '@Employee', Type: 'VARCHAR', Value: params.employee, },
                    { Name: '@Length', Type: 'FLOAT', Value: params.pieceLength, },
                    { Name: '@IsColdLength', Type: 'INT', Value: params.isColdLength }
                ];
                _.each(this.fixedParameters, function (qpParams) {
                    qp.Add(qpParams.Name, qpParams.Type, qpParams.Value);
                });
                Core.Json.CallProcedure(
                    app.DatabaseNames.MES + '.CAS.UpsertTaggingCommand',
                    qp,
                    {
                        onSuccess: function (resp) {
                            try {
                                if ((resp) && (resp.Table)) {
                                    app.views.topMessages.showMessage('Tagging in process...', { stay: 5000, });
                                    if (that.bus) that.bus.trigger('modalAcceptBtn');
                                }
                                else {
                                    if ((resp) && (resp.Message)) {
                                        console.error(new Error(resp.Message).stack);
                                        app.views.topMessages.showMessage('CALL TO DATABASE FAILED', { stay: 5000, });
                                    }
                                    else {
                                        app.views.topMessages.showMessage('SERVER RESPONSE NOT VALID', { stay: 5000, });
                                        console.error(new Error('SERVER_RESPONSE_NOT_VALID').stack);
                                    }
                                }
                            }
                            catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                        },
                        onFailure: function (resp) {
                            console.error(resp);
                        },
                        Secured: true,
                        Async: true,
                    },
                    app.ConnectionStrings.app
                );
                return this;
            },

            form_submit: function (e) {
                try { e.preventDefault(); }
                catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
            },
            modal_hidden: function (e) {
                try {
                    this.visible = false;
                    if (!this.preventDispose)
                        this.close();
                    else
                        this.preventDispose = false;
                }
                catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
            },
            modal_show: function (e) {
                try { this.visible = true; }
                catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
            },
            modal_shown: function (e) {
                try { this.$el.find(".autofocus").focus(); }
                catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
            },
            view_render: function () {
                try {
                    this.show();
                    this.updateColdLength();
                    var mode = this.model.get('printLengthMode') || 'hot';
                    var $grp = this.$el.find("#printLengthToggle");
                    $grp.find("label").removeClass("active");
                    $grp.find("input[name='printLengthModeModal']").prop("checked", false);
                    $grp.find("input[value='" + mode + "']").prop("checked", true).closest("label").addClass("active");
                    this.syncPrintLengthToggleUI(mode);
                    $grp.find("input[name='printLengthModeModal']")
                        .prop("disabled", true)
                        .addClass("disabled");
                    $grp.find("label").css({
                        pointerEvents: "none",
                        opacity: 0.6,
                        cursor: "default"
                    });
                    this.$el.find('#pieceLengthInput, #coldLengthInput')
                        .prop('disabled', true)
                        .addClass('disabled');
                }
                catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
            },

            onPrintLengthToggleClick: function (e) {
                var $label = $(e.currentTarget);
                var $grp = $label.closest("#printLengthToggle");
                var $input = $label.find("input[type='radio']");
                $grp.find("label").removeClass("active");
                $grp.find("input[type='radio']").prop("checked", false);
                $label.addClass("active");
                $input.prop("checked", true).trigger("change");
            },
            syncPrintLengthToggleUI: function (mode) {
                var $grp = this.$el.find("#printLengthToggle");
                var $hot = $grp.find("input[value='hot']").closest("label");
                var $cold = $grp.find("input[value='cold']").closest("label");

                $grp.find("label").removeClass("active btn-hot-active btn-cold-active btn-inactive");
                $hot.addClass("btn-inactive");
                $cold.addClass("btn-inactive");

                if (mode === 'hot') {
                    $hot.removeClass("btn-inactive").addClass("active btn-hot-active");
                } else {
                    $cold.removeClass("btn-inactive").addClass("active btn-cold-active");
                }

                var $hotInput = this.$el.find('#pieceLengthInput');
                var $coldLabel = this.$el.find('#coldLengthLabel');
                $hotInput.removeClass('active-length-input');
                if ($coldLabel.length) $coldLabel.removeClass('active-length-pill pill-blue pill-red');

                if (mode === 'hot') {
                    $hotInput.addClass('active-length-input');
                    if ($coldLabel.length) $coldLabel.addClass('active-length-pill pill-red');
                } else {
                    if ($coldLabel.length) $coldLabel.addClass('active-length-pill pill-blue');
                }
            },
            updateColdLength: function () {
                var val = this.model.get('pieceLength');
                var $cold = this.$el.find('#coldLengthInput');
                if (!isNaN(val) && val !== null && val !== "") {
                    var factor = parseFloat(this.model.get('coldConversionFactor') || 1.012);
                    var cold = parseFloat(val) / factor;
                    $cold.val(Math.round(cold * 100) / 100);
                } else {
                    $cold.val('');
                }
            },
            onPrintLengthModeChange: function () {
                var mode = this.$el.find("input[name='printLengthModeModal']:checked").val();
                this.model.set('printLengthMode', mode);
                this.syncPrintLengthToggleUI(mode);
            },
        });


        //-------------------------------//
        //------ Edit Length Modal ------//
        //-------------------------------//
        Screen.Models.EditLength = Backbone.Epoxy.Model.extend({
            defaults: {
                productId: null,
                productNumber: null,
                hotLength: null,
                coldConversionFactor: 1.012,
                editLengthMode: 'hot'
            }
        });

        Screen.Views.EditLengthModal = Backbone.Epoxy.View.extend({
            template: "caster-products",
            id: "edit-length-modal",
            className: "modal modal-edit-length hide fade",
            bindings: "data-bind",
            isCacheable: true,
            events: function () {
                return {
                    "click #saveEditLengthBtn": this.save_click,
                    "hidden.bs.modal": this.modal_hidden,
                    "click #savePrintEditLengthBtn": this.save_and_print_click,
                    "click #editLengthToggle label": "onToggleClick",
                    "change input[name='editLengthMode']": "onModeChange",
                    "input #editHotInput": this.handleHotChange,
                    "input #editColdInput": this.handleColdChange
                };
            },

            initialize: function (options) {
                _.extend(this, options);
                if (!this.model) this.model = new Screen.Models.EditLength();

                var d = options.data || {};
                this.model.set({
                    productId: d.Id,
                    productNumber: d.ProductNumber,
                    hotLength: d.Length,
                    editLengthMode: 'hot'
                });
                this.openPrintAfterSave = false;
                return this;
            },

            render: function (container) {
                if (container) this.container = container;

                var that = this;
                var customPath = '/app/pages/caster/caster-products/';
                T.render.call(this, this.template, function (tmp) {
                    if (!that.i18n) that.i18n = {};
                    app.getI18NJed(that, that.template, function (i18nJED) {
                        that.i18n[that.template] = i18nJED;
                        that.$el.html(tmp(that.model.toJSON()));
                        that.applyBindings();
                        that.afterRender();
                    }, true, customPath);
                }, customPath, "edit_length_modal");
            },

            afterRender: function () {
                var hot = this.model.get('hotLength');
                this.$el.find('#editHotInput').val(hot != null ? hot : '');
                this.updateColdFromHot();

                var mode = this.model.get('editLengthMode') || 'hot';
                var $grp = this.$el.find("#editLengthToggle");
                $grp.find("label").removeClass("active");
                $grp.find("input[name='editLengthMode']").prop("checked", false);
                $grp.find("input[value='" + mode + "']").prop("checked", true)
                    .closest("label").addClass("active");

                this.setInputsEnabled(mode);
                this.syncEditToggleUI(mode);

                this.$el.modal({ keyboard: true, backdrop: 'static' });
            },

            show: function () {
                if (!this.$el.children().length) this.render();
                else this.$el.modal({ keyboard: true, backdrop: 'static' });
                return this;
            },

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

            onToggleClick: function (e) {
                var $label = $(e.currentTarget);
                var $grp = $label.closest("#editLengthToggle");
                var $input = $label.find("input[type='radio']");
                $grp.find("label").removeClass("active");
                $grp.find("input[type='radio']").prop("checked", false);
                $label.addClass("active");
                $input.prop("checked", true).trigger("change");
            },

            onModeChange: function () {
                var mode = this.$el.find("input[name='editLengthMode']:checked").val();
                this.model.set('editLengthMode', mode);
                this.setInputsEnabled(mode);
                this.syncEditToggleUI(mode);
            },

            setInputsEnabled: function (mode) {
                var $hot = this.$el.find('#editHotInput');
                var $cold = this.$el.find('#editColdInput');
                if (mode === 'cold') {
                    $hot.prop('disabled', true).addClass('disabled');
                    $cold.prop('disabled', false).removeClass('disabled').focus();
                } else {
                    $hot.prop('disabled', false).removeClass('disabled').focus();
                    $cold.prop('disabled', true).addClass('disabled');
                }
            },

            handleHotChange: function () {
                var raw = this.$el.find('#editHotInput').val();
                var hot = (raw === '' ? null : parseFloat(raw));
                if (isNaN(hot) || hot === null) {
                    this.model.set('hotLength', null);
                    this.$el.find('#editColdInput').val('');
                    return;
                }
                this.model.set('hotLength', hot);
                this.updateColdFromHot();
            },

            handleColdChange: function () {
                var raw = this.$el.find('#editColdInput').val();
                var cold = (raw === '' ? null : parseFloat(raw));
                if (isNaN(cold) || cold === null) {
                    this.model.set('hotLength', null);
                    this.$el.find('#editHotInput').val('');
                    return;
                }
                var factor = parseFloat(this.model.get('coldConversionFactor') || 1.012);
                var hot = cold * factor;
                hot = Math.round(hot * 100) / 100;
                this.model.set('hotLength', hot);
                this.$el.find('#editHotInput').val(hot);
            },

            updateColdFromHot: function () {
                var hot = this.model.get('hotLength');
                var $cold = this.$el.find('#editColdInput');
                if (hot == null || isNaN(hot)) { $cold.val(''); return; }
                var factor = parseFloat(this.model.get('coldConversionFactor') || 1.012);
                var cold = hot / factor;
                cold = Math.round(cold * 100) / 100;
                $cold.val(cold);
            },

            save_click: function () {
                this.openPrintAfterSave = false;
                this._doSave();
            },

            save_and_print_click: function () {
                this.openPrintAfterSave = true;
                this._doSave();
            },

            _doSave: function () {
                var mode = this.model.get('editLengthMode');
                var isCold = (mode === 'cold') ? 1 : 0;

                var value = (isCold === 1)
                    ? parseFloat(this.$el.find('#editColdInput').val())
                    : parseFloat(this.$el.find('#editHotInput').val());

                if (isNaN(value)) {
                    app.views.topMessages.showMessage('Please enter a valid length.', { stay: 3000 });
                    return;
                }
                value = Math.round(value * 100) / 100;

                this.updateProductLength({
                    productId: this.model.get('productId'),
                    length: value,
                    isColdLength: isCold
                });
            },

            syncEditToggleUI: function (mode) {
                var $grp = this.$el.find("#editLengthToggle");
                var $hot = $grp.find("input[value='hot']").closest("label");
                var $cold = $grp.find("input[value='cold']").closest("label");

                $grp.find("label").removeClass("active btn-hot-active btn-cold-active btn-inactive");
                $hot.addClass("btn-inactive");
                $cold.addClass("btn-inactive");

                if (mode === 'hot') {
                    $hot.removeClass("btn-inactive").addClass("active btn-hot-active");
                } else {
                    $cold.removeClass("btn-inactive").addClass("active btn-cold-active");
                }
            },

            updateProductLength: function (params) {
                var qp = new Core.Database.QueryParameters();
                [
                    { Name: '@ProductId', Type: 'INT', Value: params.productId },
                    { Name: '@Length', Type: 'FLOAT', Value: params.length }
                ].forEach(function (p) { qp.Add(p.Name, p.Type, p.Value); });

                var that = this;

                Core.Json.CallProcedure(
                    app.DatabaseNames.MES + '.CAS.UpdateProductLength',
                    qp,
                    {
                        onSuccess: function (resp) {
                            app.views.topMessages.showMessage('Length updated.', { stay: 3000 });

                            if (that.bus) that.bus.trigger('modalAcceptBtn');

                            if (that.openPrintAfterSave) {
                                that.openPrintModalAfterSave(params);
                            }

                            that.$el.modal('hide');
                            that.remove();
                            that.unbind();
                        },
                        onFailure: function (resp) {
                            console.error(resp);
                        },
                        Secured: true,
                        Async: true
                    },
                    app.ConnectionStrings.app
                );
            },

            openPrintModalAfterSave: function (saveParams) {
                var hotLen = this.model.get('hotLength');
                var productId = this.model.get('productId');
                var productNumber = this.model.get('productNumber');

                if (isNaN(hotLen) || hotLen == null) {
                    hotLen = saveParams.length;
                }

                var printModal = new Screen.Views.PrintTagConfirmationModal({
                    data: {
                        Id: productId,
                        ProductNumber: productNumber,
                        Length: hotLen
                    },
                    bus: this.bus
                });

                printModal.show();
            },
        });

        // Required, return the module for AMD compliance.
        return Screen;
    });
