//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)
//mo3
define([
  // Application variable, always include it to have access to app methods.
  "app",

  //templates-loader: this loads templates async.
  "js/templates-loader",
  "modules/modal2",
  "backgrid",
  "moment",
  "modules/furnace/furnace",

  'backgrid/moment-cell',
  'backgrid/select-integer-cell',
  'backgrid/duration-cell',
  'js/backgrid-0.3.5/extensions/valid-limit-cell/backgrid-valid-limit-cell',
  'backgrid/grouped-columns',
  'js/typeahead.extended/typeahead.extended'
],

function (app, T, Modal, Backgrid, moment, Furnace) {
    //replace all "Screen" with your view's name.
    var Screen = { Models: {}, Views: {}, Collections: {} };

    Screen.Models.Main = Backbone.Epoxy.Model.extend({
        defaults: {
            positions: [],
            
            meltOrderName: null,
            gradeName: null,
            materialSizeSearch: null, 

            isLoading: true,
            hasData: false,
        },
        computeds: {
            hasPositions: {
                deps: ['positions'],
                get: function (positions) {
                    return positions.length != 0;
                },
            },
        },

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

            Core.Json.CallProcedure(
                app.DatabaseNames.MES + ".LAD.GetMeltOrders",
                qp,
                {
                    onSuccess: function (resp) {
                        try {
                            if ((resp) && (resp.Table)) {
                                var records = resp.Table;

                                var newItems = _.map(records, function (obj) { return { value: obj.Id, label: obj.Name, }; });

                                that.set("positions", newItems);
                            }
                            else {
                                if ((resp) && (resp.Message))
                                    console.error(resp.Message);
                                else
                                    console.error("Server response not valid.");
                            }
                        }
                        catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                    },
                    onFailure: function (resp) {
                        console.error(resp);
                    },
                    Secured: true,
                    Async: true,
                },
                app.ConnectionStrings.app
            );

            return this;
        }
    });



    Screen.Models.Item = Backbone.Epoxy.Model.extend({
        defaults: {
            meltOrderNumber: null,
            gradeName: null,
            heatsOrdered: null,
            heatsCast: null,
            heatsAssigned: null,
            heatsLeft: null,
            heatSize: null,
            materialSize: null,
            status: null,
            hasTWI: null,
            meltSequence: null,
            isLoading: false,
        },
        parse: function (obj) {
            return {
                meltOrderNumber: obj.MeltOrderNumber,
                gradeName: obj.GradeName,
                heatsOrdered: obj.HeatsOrdered,
                heatsCast: obj.HeatsCast,
                heatsAssigned: obj.HeatsAssigned,
                heatsLeft: obj.HeatsLeft,
                heatSize: obj.HeatSize,
                materialSize: obj.MaterialSize,
                status: obj.Status,
                hasTWI: obj.HasTWI,
                meltSequence: obj.MeltSequence,
                MESPriority: obj.MESPriority,
                optChangePosition: obj.Option_ChangePosition,

            };
        },
    });

    Screen.Collections.Items = Backbone.Collection.extend({
        model: Screen.Models.Item,

        fixedParameters: [],
        isFetching: false,
        currentPage: 1,
        pageSize: 100,

        transaction_timestamp: null,

        fetch: function (opt) {
            var that = this,
                qp = new Core.Database.QueryParameters(),
                ttimestamp = this.transaction_timestamp = new Date().getTime(),
                options = opt ? _.clone(opt) : {};
            //qp.Add('@onlyActives', 'BIT', false);

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

                this.fixedParameters = [
                    { Name: '@PartialMeltOrder', Type: 'VARCHAR', Value: options.params.PartialMeltOrder, },
                    { Name: '@PartialGradeName', Type: 'VARCHAR', Value: options.params.PartialGradeName, },
                    { Name: '@MaterialSize', Type: 'VARCHAR', Value: options.params.MaterialSize, },
                ];
            }
            this.isFetching = true;

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

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


            Core.Json.CallProcedure(
                app.DatabaseNames.MES + '.LAD.GetMeltOrders',
                qp,
                {
                    onSuccess: function (resp) {
                        try {
                            //checking transaction timestamp
                            if (ttimestamp != that.transaction_timestamp)
                                return;

                            if ((resp) && (resp.Table)) {
                                var records = resp.Table,
                                    newColl;

                                newColl = _.map(records, that.model.prototype.parse);

                                var method = ((options.reset) || (options.refresh)) ? 'set' : 'add';

                                if (options.reset)
                                    that.reset();

                                that[method](newColl)
                                    .trigger('fetch', that, resp);

                                if (newColl.length == 0 && method == 'add')
                                    that.currentPage--;

                                that.isFetching = false;
                            }
                            else {
                                if ((resp) && (resp.Message))
                                    console.error(resp.Message);
                                else
                                    console.error('Server response not valid.');
                            }
                        }
                        catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                    },
                    Async: true,
                    Secured: true,
                },
                app.ConnectionStrings.app
            );

            return this;
        },
        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);
            }
        },
        getGridId: function () {
            return 'gridContainer';
        },
    });

    Screen.Models.DetailTable = Backbone.Epoxy.Model.extend({
        defaults: {
            meltOrderSequence: null,
            heatNumber: null,
            ladle: null,
            ladlePosition: null,
        },
        parse: function (obj) {
            return {
                meltOrderSequence: obj.MeltOrderSequence,
                heatNumber: obj.HeatNumber,
                ladle: obj.Ladle,
                ladlePosition: obj.LadlePosition,
            }
        }
    });

    Screen.Collections.DetailsTable = Backbone.Collection.extend({
        model: Screen.Models.DetailTable,

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

        fetch: function (opt) {
            var that = this,
                qp = new Core.Database.QueryParameters(),
                ttimestamp = this.transaction_timestamp = new Date().getTime(),
                options = opt ? _.clone(opt) : {};

            this.isFetching = true;

            //if (options.reset) {
            //this.resetPagination(true);

            this.fixedParameters = [
                { Name: '@MeltOrderNumber', Type: 'VARCHAR', Value: options.params.meltOrderNumber, },
            ];
            //}

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

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


            Core.Json.CallProcedure(
                app.DatabaseNames.MES + ".LAD.GetMeltOrderDetails",
                qp,
                {
                    onSuccess: function (resp) {
                        try {
                            //checking transaction timestamp
                            if (ttimestamp != that.transaction_timestamp)
                                return;

                            if ((resp) && (resp.Table) && (resp.Table1)) {
                                var records = resp.Table1,
                                    newColl;

                                newColl = _.map(records, that.model.prototype.parse);

                                var method = ((options.refresh) || ((options.reset))) ? 'set' : 'add';

                                //checking transaction timestamp
                                if (ttimestamp != that.transaction_timestamp)
                                    return;

                                if (!options.reset) {
                                    var editingItems = _.where(that.toJSON(), { isNew: true });
                                    [].push.apply(newColl, editingItems);
                                }

                                that[method](newColl, { from: 'fetch' })
                                    .trigger('fetch', that, records);

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

                                that.isFetching = false;
                            }
                            else {
                                if ((resp) && (resp.Message))
                                    console.error(resp.Message);
                                else
                                    console.error('Server response not valid.');
                            }
                        }
                        catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                    },
                    Async: true,
                    Secured: true,
                },
                app.ConnectionStrings.app
            );

            return this;
        },
    });

    Screen.Models.MeltOrderDetails = Backbone.Epoxy.Model.extend({
        defaults: {
            message: null,

            errorMsg: "",
            processing: false,
        },
    });

    Screen.Views.MeltOrderDetails = Modal.Views.SimpleModal.extend({
        className: Modal.Views.SimpleModal.prototype.className + ' melt-order-details',
        i18n: null,
        detailsTable: null,
        detailsGrid: null,
        initialize: function (options) {
            _.extend(this, options);

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

            this.detailsTable = new Screen.Collections.DetailsTable();
            this.detailsTable.fetch(
                {
                    params: {
                        meltOrderNumber: this.model.get('meltOrderNumber'),
                    },
                }
            );
            this.bindEvents();

            return this;
        },
        bindEvents: function () {
            Modal.Views.SimpleModal.prototype.bindEvents.apply(this, arguments);
        },
        render: function () {
            Modal.Views.SimpleModal.prototype.render.apply(this, arguments);

            var detailsGrid = this.detailsGrid = new Backgrid.Grid({
                className: 'backgrid table table-hover',
                columns: [
                    {
                        name: 'meltOrderSequence',
                        label: app.translate([this, app], 'melt_sequence_col_label'),
                        editable: false,
                        sortable: false,
                        cell: Backgrid.StringCell.extend({
                            orderSeparator: '',
                            className: 'string-cell align-center-cell',
                        }),
                    },
                    {
                        name: 'heatNumber',
                        label: app.translate([this, app], 'heat_number_col_label'),
                        editable: false,
                        sortable: false,
                        cell: Backgrid.StringCell.extend({
                            orderSeparator: '',
                            className: 'string-cell align-center-cell',
                        }),
                    },
                    {
                        name: 'ladle',
                        label: app.translate([this, app], 'ladle_col_label'),
                        editable: false,
                        sortable: false,
                        cell: Backgrid.StringCell.extend({
                            orderSeparator: '',
                            className: 'string-cell align-center-cell',
                        }),
                    },
                    {
                        name: 'ladlePosition',
                        label: app.translate([this, app], 'ladle_position_col_label'),
                        editable: false,
                        sortable: false,
                        cell: Backgrid.StringCell.extend({
                            orderSeparator: '',
                            className: 'string-cell align-center-cell',
                        }),
                    },
                ],
                collection: this.detailsTable,
            });

            this.$el.find('.details-grid-container').append(detailsGrid.render().el);
        },

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

            return this;
        },
        hide: function () {
            //if (this.innerModal)
            //    this.innerModal.hide();

            var result = Modal.Views.SimpleModal.prototype.hide.apply(this, arguments);
            return result;
        },

        closeBtn_click: function (e) {
            try {
                this.hide();
            }
            catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
        },
    });
    //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.
    Screen.generateID = function (viewParams) {
        try {
            //if the viewparams change the view id, then evaluate the viewparams here
            //and return the appropiate id.
            return "melt-orders";
        } catch (Error) { }
    };

    Screen.Views.Main = Backbone.Epoxy.View.extend({
        template: "melt-orders",
        id: "melt-orders",
        title: "Melt Orders",
        //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,
                'mousedown .draggable': this.mouseDownHandler,
                'mousemove .draggable': this.mouseMoveHandler,
                'mousemove #content': this.mouseMoveHandler,
                'mouseup': this.mouseUpHandler,
                'mousemove #lastrow': this.mouseMoveLastRowHandler,
                'mouseout #lastrow': this.mouseOutLastRowHandler,
            };
        },

        autoRefresh: null,
        bindingSources: null,
        grids: null,
        items: null,
        subviews: null,

        templates: null,

        currentModal: null,
        listeners: null,

        //Drag and Drop Variables
        table: null,
        draggingEle: null,
        draggingRowIndex: null,
        placeholder: null,
        list: null,
        isDraggingStarted: false,
        x: null,
        y: null,
        dragEnabled: false,
        container: null,

        dropModel: null,
        dragModel: null,

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

            var that = this;

            this.autoRefresh = {
                enabled: null
                , toid: null
                , every: 5 * 1000
            };

            this.templates = {
                meltOrderDetails: null,
            };

            this.model = new Screen.Models.Main();
           // this.model.fetchPositions();

            this.items = new Screen.Collections.Items();

            this.grids = {};

            this.bindingSources = {};

            this.listeners = {};

            this.bindEvents();
        },

        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.items, 'fetch', this.collection_fetch);
            this.listenTo(this.model, "change:meltOrderName change:gradeName change:materialSizeSearch", _.debounce(this._search_changed, 800));
        },
        getPermissions: function () {
            var write = $.inArray('lad_meltorders_readWrite', app.models.user.get('roles'));
            var ctx = {
                write: write != -1 ? true : false,
            };
            return ctx.write;
        },

        // Drag and Drop Functions
        mouseMoveLastRowHandler: function () {
            if (this.isDraggingStarted) {
                var that = this;
                var grid = that.grids;
                var lastRow = grid.items.body.rows[grid.items.body.rows.length - 1];
                lastRow.el.classList.add('lastRow');
                this.dropModel = null;
            }
        },
        mouseOutLastRowHandler: function () {
            var that = this;
            var grid = that.grids;
            var lastRow = grid.items.body.rows[grid.items.body.rows.length - 1];

            if (lastRow && lastRow.el && lastRow.el.className && lastRow.el.className == 'lastRow') {
                lastRow.el.classList.remove('lastRow');
            }

        },

        makeDraggableRows: function () {
            var that = this;
            this.table = document.getElementById('gridContainer');
            this.table.querySelectorAll('tr').forEach(function (row, index) {
                if (index === 0) {
                    return;
                }
                var firstCell = row.firstElementChild;
                if (that.getPermissions()) {
                    firstCell.classList.add('draggable');
                    firstCell.classList.add('dropable');
                }
            });
        },

        mouseDownHandler: function (e) {
            var originalRow = e.target.parentNode;


            this.draggingRowIndex = [].slice.call(this.table.querySelectorAll('tr')).indexOf(originalRow);
            if (this.draggingRowIndex == '-1' || !this.draggingRowIndex) {
                originalRow = originalRow.parentNode;
                this.draggingRowIndex = [].slice.call(this.table.querySelectorAll('tr')).indexOf(originalRow);
                if (this.draggingRowIndex == '-1' || !this.draggingRowIndex) {
                    originalRow = originalRow.parentNode;
                    this.draggingRowIndex = [].slice.call(this.table.querySelectorAll('tr')).indexOf(originalRow);
                }
            }
            this.x = e.clientX;
            this.y = e.clientY + window.scrollY;
            this.dragEnabled = true;

        },
        mouseMoveHandler: function (e) {
            if (this.dragEnabled) {
                var that = this;
                if (this.isDraggingStarted) {
                    if (this.draggingEle) {
                        var offsetTop = this.draggingEle.offsetTop;
                        this.draggingEle.style.top = (offsetTop + e.clientY - parseInt(this.y)) + 'px';
                    }
                }

                if (!this.isDraggingStarted) {
                    this.isDraggingStarted = true;

                    this.cloneTable();
                    this.draggingEle = [].slice.call(this.list.children)[this.draggingRowIndex];
                    this.draggingEle.classList.add('dragging');

                    var table = [].slice.call(this.draggingEle.children)[0];
                    table.querySelectorAll('td').forEach(function (td, index) {
                        if (index === 0) {
                            td.classList.add('dragging');
                            td.classList.remove('draggable');
                        }
                    });

                    this.draggingEle.classList.remove('draggable');

                    this.draggingEle.style.top = parseInt(this.y) + 'px';

                    this.draggingEle.style.position = 'absolute';
                    this.table.parentNode.insertBefore(this.draggingEle, this.table);

                }
                // Reassign the position of mouse
                this.x = e.clientX;
                this.y = e.clientY;
            }
        },


        cloneTable: function () {
            var rect = this.table.getBoundingClientRect();
            var width = parseInt(window.getComputedStyle(this.table).width);
            this.list = document.createElement('div');
            this.list.classList.add('clone-list');
            this.list.style.position = 'absolute';
            this.list.style.left = `${rect.left}px`;
            this.list.style.top = `${rect.top}px`;

            var that = this;
            this.table.querySelectorAll('tr').forEach(function (row) {
                var item = document.createElement('div');
                item.classList.add('draggable');

                var newTable = document.createElement('table');
                newTable.setAttribute('class', 'clone-table');
                newTable.style.width = `${width}px`;

                var newRow = document.createElement('tr');
                var cells = [].slice.call(row.children);
                cells.forEach(function (cell) {
                    var newCell = cell.cloneNode(true);
                    newCell.style.width = `${parseInt(window.getComputedStyle(cell).width)}px`;
                    newRow.appendChild(newCell);
                });

                newTable.appendChild(newRow);
                item.appendChild(newTable);
                that.list.appendChild(item);
            });

        },

        removeClassPlaceholder: function () {
            var placeholder = document.getElementsByClassName("placeholder");
            if (placeholder.length > 0)
                placeholder[0].classList.remove("placeholder");
        },

        mouseUpHandler: function () {
            var that = this;
            this.dragEnabled = false;
            this.isDraggingStarted = false;
            if (this.draggingEle && this.draggingEle.parentNode) {
                this.removeClassPlaceholder();
                this.draggingEle.parentNode.removeChild(this.draggingEle);
                this.Move({
                    success: function () {
                        app.views.topMessages.showMessage(app.translate([that, app], 'MELT_ORDER_PRIORITY_CHANGED'), { stay: 5 * 1000, });

                        that._refresh({
                            refresh: true,
                            reset: false,
                        });
                    },
                    error: function () {
                        app.views.topMessages.showMessage(app.translate([that, app], 'MELT_ORDER_PRIORITY_ERROR'), { stay: 5 * 1000, });
                    }
                });
            }
        },


        // Common functions
        collection_fetch: function (coll, resp) {
            try {
                var that = this;
                setTimeout(
                    function () {
                        that.model.set({
                            hasData: (that.items.length > 0),
                            isLoading: false,
                        });
                    },
                    100
                );
                this.makeDraggableRows();

                if (that.items.length > 0)
                    that.scrollToBottomTrigger(that.items);
            }
            catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
        },

        scrollToBottomTrigger: function (collection) {
            var docHeight = $(document).height(),
                viewportHeight = $(window).height(),
                scrollTop = $(window).scrollTop();
            window.addEventListener('scroll', function () {
                docHeight = $(document).height();
                viewportHeight = $(window).height();
                scrollTop = $(window).scrollTop();
                if ((scrollTop != 0) && (viewportHeight + scrollTop > docHeight - 100)) {
                    collection.getNextPage();
                }
            });
        },
        refreshBtn_click: function () {
            this.model.set({
                hasData: false,
                isLoading: true,

            })
            this.refreshItemsColl();
        },

        _refresh: function (opt) {
            if (this.autoRefresh.toid != null) {
                clearTimeout(this.autoRefresh.toid);
                this.autoRefresh.toid = null;
            }
            this.refreshItemsColl(_.extend(
                {},
                opt,
                {
                    params: {}
                })
            );

            if (this.autoRefresh.enabled == true) {
                var that = this;

                this.autoRefresh.toid = setTimeout(
                    function () { that._refresh(); },
                    60 * 1000
                );
            }
        },
        refresh: function (viewParams) {
            var fixedParams = _.extend({}, Screen.Models.Main.prototype.defaults, viewParams);

            //If currentModal exists, hide it and erase it.
            if (this.currentModal) {
                this.currentModal.hide();
                this.currentModal = null;
            }

            //Call first refresh.
            var params = this.model.toJSON();

            this._refresh(_.extend(
                {},
                params,
                {
                    reset: true,
                    params: _.extend(
                        {},
                        params,
                        {}
                    ),
                }
            ));
        },
        refreshItemsColl: function (options) {
            try {
                var that = this,
                    modelAttrs = this.model.toJSON(),
                    opt = _.extend({}, { params: {}, refresh: true, }, options);

                //var agentId = ()
                //                ? opt.params.agentId
                //                : (modelAttrs.agentId)
                //                    ? modelAttrs.agentId
                //                    : null;

                if (opt.reset == true) {
                    this.model.set({
                        isLoading: true,
                    });
                }

                //Parameter details:
                // > Parameter 'reset' is used to reload only the first page of records and
                // show the 'Loading' poster.
                // > Parameter 'refresh' is uset to reload all the currently loaded records
                // without showing the 'Loading' poster.
                this.items.fetch({
                    params: {
                        PartialMeltOrder: modelAttrs.meltOrderName,
                        PartialGradeName: modelAttrs.gradeName,
                        MaterialSize: modelAttrs.materialSizeSearch
                    },
                    refresh: true,
                    //refresh: opt.refresh,
                    //reset: opt.reset,
                });
            }
            catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
        },
        render: function (container, viewParams) {
            var that = this;

            this.viewParams = viewParams;

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

            //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/' + this.template + '/';

            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;
                            //start: before the view is visible, but the template was already loaded (not instanced nor appended)

                            //end:

                            //CREATE AN OBJECT AND SET A PROPERTY CALLED EDITABLE THAT I WILL USE IN ASPX WITH HANDLEBARS TO ENABLE OR DISABLE A SECTION
                            // ALSO I CREATE AN OBJECT CALLED PERMISSIONS, THAT I WILL USE AS MUCH IN ASPX AS IN JS
                            var ctx = {
                                editable: (($.inArray("AdminUserRole", app.models.user.get("roles")) != -1
                                    || $.inArray("SupervisorUserRole", app.models.user.get("roles")) != -1) ? true : false),
                                permissions: {
                                    edit: (($.inArray("scrapyard_recipes_item_edit", app.models.user.get("roles")) != -1) ? true : null),
                                    download_all: (($.inArray("scrapyard_recipes_download_all", app.models.user.get("roles")) != -1) ? true : null),
                                    download_recipe: (($.inArray("scrapyard_recipes_download", app.models.user.get("roles")) != -1) ? true : null),
                                },
                            };

                            //SEND CTX TO ASPX SO I CAN MANIPULATE WITH HANDLEBARS
                            that.$el.html(tmp(_.extend({}, ctx, (that.model) ? that.model.toJSON() : {})));
                            that.applyBindings();
                            ////loading the view and appeding it to the views's $el.
                            //that.$el.html(tmp());
                            //that.applyBindings();

                            that.bindViewScopedEvents();

                            //start: the view was already loaded an is on a div element, but not appended to the main container
                            //here you can perform anything you want DOM related, by getting the dom element via that.$el.find("#id")
                            //or this.$("#id")

                            that.templates.meltOrderDetails = Handlebars.compile(that.$el.find('#melt_order_details_modal_template').html());

                            var columns = [
                                {
                                    name: 'meltOrderNumber',
                                    label: app.translate([that, app], 'meltOrderNumber_col_label'),
                                    editable: false,
                                    sortable: false,
                                    cell: Backgrid.StringCell.extend({
                                        orderSeparator: '',
                                        className: 'string-cell align-center-cell meltOrderNumber',
                                    }),
                                },
                                {
                                    name: 'gradeName',
                                    label: app.translate([that, app], 'gradeName_col_label'),
                                    editable: false,
                                    sortable: false,
                                    cell: Backgrid.StringCell.extend({
                                        orderSeparator: '',
                                        className: 'string-cell align-center-cell gradeName',
                                    }),
                                },
                                {
                                    name: 'heatsOrdered',
                                    label: app.translate([that, app], 'heatsOrdered_col_label'),
                                    editable: false,
                                    sortable: false,
                                    cell: Backgrid.NumberCell.extend({
                                        decimals: 0,
                                        className: 'numeric-cell align-center-cell heatsOrdered',
                                    }),
                                },
                                {
                                    name: 'heatsAssigned',
                                    label: app.translate([that, app], 'heatsAssigned_col_label'),
                                    editable: false,
                                    sortable: false,
                                    cell: Backgrid.NumberCell.extend({
                                        decimals: 0,
                                        className: 'numeric-cell align-center-cell heatsCast',
                                    }),
                                },
                                {
                                    name: 'heatsLeft',
                                    label: app.translate([that, app], 'heatsLeft_col_label'),
                                    editable: false,
                                    sortable: false,
                                    cell: Backgrid.NumberCell.extend({
                                        decimals: 0,
                                        className: 'numeric-cell align-center-cell heatsLeft',
                                    }),
                                },
                                {
                                    name: 'heatSize',
                                    label: app.translate([that, app], 'heatSize_col_label'),
                                    editable: false,
                                    sortable: false,
                                    cell: Backgrid.NumberCell.extend({
                                        decimals: 0,
                                        className: 'numeric-cell align-center-cell heatSize',
                                    }),
                                },
                                {
                                    name: 'materialSize',
                                    label: app.translate([that, app], 'materialSize_col_label'),
                                    editable: false,
                                    sortable: false,
                                    cell: Backgrid.StringCell.extend({
                                        orderSeparator: '',
                                        className: 'numeric-cell align-center-cell materialSize',
                                    }),
                                },
                                {
                                    name: "options",
                                    label: "",
                                    sortable: false,
                                    editable: false,
                                    //renderable: (_.isBoolean(ctx.editable)) ? ctx.editable : false,
                                    headerCell: Backgrid.HeaderCell.extend({
                                        className: "optionstd",
                                    }),
                                    cell: Backgrid.Cell.extend({
                                        template: Handlebars.compile(that.$el.find('#actions_cell_template').html()),
                                        className: 'actions-cell',
                                        events: {
                                            'click .btn-cell-action': 'cellActionClick',

                                            "click .btn-dropdown-config-option": "configure_dropdown_config_opt_click",
                                            //"click .btn-dropdown-action-option": "configure_dropdown_action_opt_click",

                                            "show.bs.dropdown .btn-group": "btnGroup_show",
                                            "hide.bs.dropdown .btn-group": "btnGroup_hide",
                                        },

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

                                            ////creating new locked attr on column
                                            //this.model.set("locked", false);

                                            //this.locksChanged();

                                            //_.bindAll(this);

                                            this.bindEvents();
                                        },
                                        render: function () {
                                            Backgrid.Cell.prototype.render.apply(this, arguments);
                                            this.$el.html(this.template(this.model.toJSON()));

                                            if (this.model.get("editing")) {
                                                this.render_newRow();
                                            } else {
                                                this.render_actions();
                                            }

                                            this.delegateEvents();
                                            return this;
                                        },
                                        render_newRow: function () {
                                            this.$el.find('[data-toggle="tooltip"]').tooltip();

                                            return this;
                                        },
                                        render_actions: function () {
                                            this.$el.find("[data-toggle=popover]").popover();

                                            //this.$el.find(".dropdown-menu").on("s", function (event) {
                                            //    alert('A');
                                            //});

                                            //this.$el.find(".dropdown-menu").on("hide.bs.dropdown", function (event) {
                                            //    alert('B');
                                            //});

                                            //if (!ctx.editable) {
                                            //  this.$el.find(".configure-source-btn").attr("disabled", true);
                                            //}

                                            this.checkAnyOptions();
                                            return this;
                                        },
                                        bindEvents: function () {
                                            this.listenTo(this.model, 'change:editing change:isLoading', this.checkMode);
                                        },
                                        /////////////////////////////////////////////////////////////////////////////////////
                                        checkMode: function () {
                                            try {
                                                this.render();
                                            } catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                                        },
                                        cellActionClick: function (e) {
                                            try {
                                                var target = $(e.target);
                                                var actionData = target.closest('[data-cell-action]').data('cell-action');
                                                if (actionData) {
                                                    that.actionOnRow(this.model, actionData);
                                                }
                                            }
                                            catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                                        },
                                        /////////////////////////////////////////////////////////////////////////////////////
                                        btnGroup_show: function (e) {
                                            try {
                                                that.stopAutoRefresh();
                                                //If there's an error, this line prevents 
                                                this.startAutoRefreshTimeoutId = setTimeout(function () { that.startAutoRefresh(); }, 60 * 1000);
                                            }
                                            catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                                        },
                                        btnGroup_hide: function (e) {
                                            try {
                                                clearTimeout(this.startAutoRefreshTimeoutId);
                                                that.startAutoRefresh();
                                            }
                                            catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                                        },
                                        checkAnyOptions: function () {
                                            var actionSourceBtn = this.$el.find(".action-source-btn");
                                            if (this.$el.find(".action-source-dropdown").find("li").length > 0) {
                                                actionSourceBtn.attr("disabled", false);
                                            } else {
                                                actionSourceBtn.attr("disabled", true);
                                            }
                                        },
                                        configure_dropdown_config_opt_click: function (e) {
                                            try {
                                                e.preventDefault();
                                                if (!$(e.target).hasClass("disabled-link")) {
                                                    that.runOption(this.model, { option: $(e.target).data("option") });
                                                }
                                            } catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                                        },
                                    }),
                                },
                            ];

                            if (that.getPermissions()) {
                                columns =[
                                    {
                                        name: 'actions',
                                        label: '',
                                        editable: false,
                                        sortable: false,
                                        cell: Backgrid.Cell.extend({
                                            template: Handlebars.compile(that.$el.find('#actions_cell_template_drag').html()),
                                            className: 'actions-cell',
                                            events: {
                                                'click .btn-cell-action': 'cellActionClick'
                                            },

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

                                            },
                                            render: function () {
                                                this.$el.html(this.template());
                                                this.delegateEvents();
                                                return this;
                                            },
                                            cellActionClick: function (e) {
                                                try {
                                                }
                                                catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                                            },
                                        }),
                                    },...columns]
                            }

                            var customRow = Backgrid.Row.extend({
                                initialize: function () {
                                    Backgrid.Row.prototype.initialize.apply(this, arguments);

                                    this.bindEvents();
                                },
                                events: {
                                    "mousedown": function (e) {
                                        that.removeClassPlaceholder();
                                        this.$el.addClass("placeholder");
                                        that.dragModel = this.model.toJSON();

                                    },
                                    "mouseup": function () {
                                        that.removeClassPlaceholder();
                                        this.el.removeAttribute("style", "border-top-color:#2aa89d !important;border-top: solid;border-top-width: 6px;");
                                    },
                                    "mouseover": function (e) {
                                        if (that.isDraggingStarted) {
                                            that.dropModel = this.model.toJSON();
                                            this.el.setAttribute("style", "border-top-color:#2aa89d !important;border-top: solid;border-top-width: 6px;");
                                        }
                                    },
                                    "mouseout": function (e) {
                                        this.el.removeAttribute("style", "border-top-color:#2aa89d !important;border-top: solid;border-top-width: 6px;");
                                    },

                                },
                                render: function () {
                                    Backgrid.Row.prototype.render.apply(this, arguments);

                                    if (this.model.get('isLoading')) {
                                        this.$el.addClass('locked-row');
                                    } else {
                                        this.$el.removeClass('locked-row');
                                    }

                                    return this;
                                },
                                bindEvents: function () {
                                    this.listenTo(this.model, 'change:isLoading', this.model_change_isLoading);
                                },
                                model_change_isLoading: function () {
                                    try {
                                        this.render();
                                    } catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                                },
                            });

                            var grid = that.grids.items = new Backgrid.Grid({
                                header: Backgrid.Extension.GroupedHeader.extend({
                                    columnLayout:
                                    [

                                        {
                                            name: 'meltOrderNumber',
                                        },
                                        {
                                            name: 'gradeName',
                                        },
                                        {
                                            name: app.translate(that, 'heats_col_header'),
                                            children: [
                                                {
                                                    name: 'heatsOrdered'
                                                },
                                                {
                                                    name: 'heatsAssigned'
                                                },
                                                {
                                                    name: 'heatsLeft'
                                                },
                                            ],
                                        },

                                 {
                                     name: 'heatSize',
                                 },
                                 {
                                     name: 'materialSize',
                                 },
                                 //{
                                 //    name: 'hasTWI',
                                 //},
                                 //{
                                 //    name: 'meltSequence',
                                 //}
                                    ],
                                }),
                                className: 'backgrid table table-hover',
                                row: that.getPermissions() ? customRow : null,
                                columns: columns,
                                collection: that.items,
                            });
                            that.$el.find('.items-grid-container').append(grid.render().el);
                          
                            //end
                            //appending view to the main container 

                            var fixedParams = _.extend({}, viewParams);

                            //Call first refresh.
                            var params = that.model.toJSON();

                            that._refresh(_.extend(
                                {},
                                params,
                                {
                                    reset: true,
                                    params: _.extend(
                                        {},
                                        params,
                                        {}
                                    ),
                                }
                            ));

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

                            //Call first refresh.
                            // that.startAutoRefresh();
                            that._refresh();
                        },
                    true,
                    customPath
                );
                },
                customPath
            );
        },
        runOption: function (model, data) {
            try {
                var that = this;
                //var row = model.attributes; 

                //var type = row.systemType;
                //var typeClass = row.systemTypeClass;
                var menu_option = (data && data.option) ? data.option : null;

                switch (menu_option.toUpperCase()) {
                    case "OPT-SHOW-DETAILS":
                        this.meltOrderDetails(model);
                        break;
                    case "MOVEUP":
                        modal = new Modal.Views.Main({
                            focusOk: false,
                            focusSelector: '#btn-cancel',
                            title: app.translate([this, app], "move_priority_modal_confirm_title"),
                            message: app.translate([this, app], "move_priority_modal_confirm_message"),
                            buttons_type: "CONTINUE-CANCEL",
                        });

                        this.listenToOnce(modal, "continue", function (modal) {
                            try {
                                that.Move(model, true, {
                                    success: function () {
                                        app.views.topMessages.showMessage(app.translate([that, app], 'MELT_ORDER_PRIORITY_CHANGED'), { stay: 5 * 1000, });

                                        that._refresh({
                                            refresh: true,
                                            reset: false,
                                        });
                                    },
                                    error: function () {
                                        app.views.topMessages.showMessage(app.translate([that, app], 'MELT_ORDER_PRIORITY_ERROR'), { stay: 5 * 1000, });
                                    }

                                });
                            }
                            catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                        });

                        modal.show();
                        
                        break;
                    case "MOVEDOWN":
                        modal = new Modal.Views.Main({
                            focusOk: false,
                            focusSelector: '#btn-cancel',
                            title: app.translate([this, app], "move_priority_modal_confirm_title"),
                            message: app.translate([this, app], "move_priority_modal_confirm_message"),
                            buttons_type: "CONTINUE-CANCEL",
                        });

                        this.listenToOnce(modal, "continue", function (modal) {
                            try {
                                that.Move(model, false, {
                                    success: function () {
                                        app.views.topMessages.showMessage(app.translate([that, app], 'MELT_ORDER_PRIORITY_CHANGED'), { stay: 5 * 1000, });

                                        that._refresh({
                                            refresh: true,
                                            reset: false,
                                        });
                                    },
                                    error: function () {
                                        app.views.topMessages.showMessage(app.translate([that, app], 'MELT_ORDER_PRIORITY_ERROR'), { stay: 5 * 1000, });
                                    }
                                });
                            }
                            catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                        });

                        modal.show();
                        break;
                }

            } catch (Error) { }
        },



        meltOrderDetails: function (model) {
            try {
                var that = this
                    , attrs = model.toJSON();

                this.currentModal = new Screen.Views.MeltOrderDetails({
                    model: new Screen.Models.MeltOrderDetails(attrs),
                    template: this.templates.meltOrderDetails,
                    i18n: this.options.i18n[this.template],
                });

                var fn_modal_shown_hidden = function () {
                    try {
                        //Enable button in both events, shown and hidden, just to prevent issues if one of them fails
                        //or it is not executed for some reason.
                        //clickedBtn.attr("disabled", false);
                    }
                    catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                };

                this.listenToOnce(this.currentModal, 'shown', fn_modal_shown_hidden)
                    .listenToOnce(this.currentModal, 'hidden', fn_modal_shown_hidden)
                    .listenToOnce(this.currentModal, 'finish', function (modal, output) {
                        try {
                            if (output.result == 'SUCCESS') {
                                app.views.topMessages.showMessage(app.translate([that, app], 'SAVED_CHANGES_SUCCESSFUL'), { stay: 5 * 1000, });
                            }
                        }
                        catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                    });;

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

        Move: function (options) {
            try {
                var that = this,
                    opt = _.extend({}, { error: function () { }, success: function () { }, }, options),
                    qp = new Core.Database.QueryParameters();

                var MeltOrderNumberToMove, MeltOrderNumberReplaced

                if (this.dragModel && this.dragModel.meltOrderNumber) MeltOrderNumberToMove = this.dragModel.meltOrderNumber;
                if (this.dropModel && this.dropModel.meltOrderNumber) MeltOrderNumberReplaced = this.dropModel.meltOrderNumber;

                qp.Add("@MeltOrderNumberToMove", "VARCHAR", MeltOrderNumberToMove);
                qp.Add("@MeltOrderNumberReplaced", "VARCHAR", MeltOrderNumberReplaced);

                Core.Json.CallProcedure(
                    app.DatabaseNames.MES + ".LAD.MoveMeltOrderPriority",
                    qp,
                    {
                        onSuccess: function (resp) {
                            try {
                                if (opt.success)
                                    opt.success();
                            }
                            catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                        },
                        onFailure: function (resp) {
                            console.error(resp);
                        },
                        Secured: true,
                        Async: true,
                    },
                    app.ConnectionStrings.app
                );
            }
            catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
        },

        //Move: function (model, up, options) {
        //    try {
        //        var that = this
        //            , attrs = model.toJSON();
        //        var that = this,
        //            qp = new Core.Database.QueryParameters();

        //        qp.Add("@MeltOrderNumber", "VARCHAR", attrs.meltOrderNumber);
        //        qp.Add("@UpDirection", "BIT", up ? 1 : 0);

        //        var opt = _.extend({} , { error: function () { }, success: function () { }, }, options);

        //        Core.Json.CallProcedure(
        //            app.DatabaseNames.MES + '.LAD.MoveMeltOrderPriorityWeb',
        //            qp,
        //            {
        //                onSuccess: function (resp) {
        //                    try {
        //                        if ((resp) && (resp.Table) && (resp.Table.length > 0)) {
        //                            if (opt.success)
        //                                opt.success();
        //                        }
        //                        else {
        //                            var errorMsg = ((resp) && (resp.Message))
        //                                                        ? resp.Message
        //                                                        : 'SERVER_RESPONSE_NOT_VALID';
        //                            console.error(errorMsg);

        //                            if (opt.error)
        //                                opt.error(that, errorMsg);
        //                        }
        //                    }
        //                    catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
        //                },
        //                onError: function (errorMsg) {
        //                    try {
        //                        if (opt.error)
        //                            opt.error(that, errorMsg);
        //                    }
        //                    catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
        //                },
        //                Async: true,
        //                Secured: true,
        //            },
        //            app.ConnectionStrings.app
        //        );
        //    }
        //    catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
        //},


        _search_changed: function () {
            try {
                this.doSearch.call(this);
            } catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
        },
        doSearch: function () {
            var meltSearch = this.model.get('meltOrderName');
            var gradeSearch = this.model.get('gradeName');
            var materialSizeSearch = this.model.get('materialSizeSearch');

            this.model.set('meltOrderName', meltSearch);
            this.model.set('gradeName', gradeSearch);
            this.model.set('materialSizeSearch', materialSizeSearch);

            var params

            this._refresh({
                refresh: true,
                reset:false,
            });
        },
        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;
            }
        },
        bindViewScopedEvents: function () {
            //TODO - Put this in events object.
            var that = this;

            this.listeners['beforeunload'] = _.bind(that.window_beforeUnload, that);
            $(window).on('beforeunload', this.listeners['beforeunload']);
        },
        close: function () {
            this.options.state = app.view_states.closed;

            //If currentModal exists, hide it and erase it.
            if (this.currentModal) {
                this.currentModal.hide();
                this.currentModal = null;
            }

            this.stopAutoRefresh();
            this.closeSubviews();
            this.remove();
            this.unbindViewScopedEvents();
            this.unbind();
        },
        closeSubviews: function () {
            _.each(this.subviews, function (sview) {
                sview.close();
            });
        },
        hide: function () {
            this.options.state = app.view_states.hidden;

            this.hideSubviews();
            this.stopAutoRefresh();

            this.$el.hide();
            this.unbind();
            this.stopListening();
        },
        hideSubviews: function () {
            _.each(this.subviews, function (sview) {
                sview.hide();
            });
        },
        remove: function () {
            this.removeBindings();
            this.$el.remove();
            this.stopListening();
            return this;
        },
        reRender: function () {
            this.startAutoRefresh();
        },
        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();
            });
        },
        startAutoRefresh: function () {
            try {
                if (this.autoRefresh.enabled !== true) {
                    var that = this;

                    if (this.autoRefresh.toid != null) {
                        clearTimeout(this.autoRefresh.toid);
                        this.autoRefresh.toid = null;
                    }

                    this.autoRefresh.enabled = true;

                    //use a timeout to execute the first refresh to return the handle to the start function caller.
                    //So when the caller finish it will do the first refresh.
                    this.autoRefresh.toid = setTimeout(
                        function () { that._refresh(); },
                        10 * 1000
                    );
                }
            } catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
        },
        stopAutoRefresh: function () {
            if (this.autoRefresh.toid != null) {
                clearTimeout(this.autoRefresh.toid);
                this.autoRefresh.toid = null;
            }
            this.autoRefresh.enabled = false;
        },
        unbindViewScopedEvents: function () {
            $(window).off('beforeunload', this.listeners['beforeunload']);

            this.stopAutoRefresh();
        },
        window_beforeUnload: function (e) {
            try {
                if (this.currentModal) {
                    this.currentModal.hide();
                }
            }
            catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
        },
    });

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

});
