/// <reference path="http://localhost:65492/IndustrialDashboard/Scripts/IndustrialDashboard-debug.js" />
//SCREEN-BOILERPLATE

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

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

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

  "modules/modal",

  "backgrid",

  "js/dashboard-assets/progressbar/progressbar",

  "oee-module-assets/dashboard-assets/jquery-circle-progress/circle-progress",

],

function (app, T, Modal, Backgrid, ProgressBar) {

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

    OEE.Models.Main = Backbone.Model.extend({
        defaults: {
            productionItem: null,
            delaysInformation: null,
            from: null, //"2015-07-30 17:40:00",
            to: null, //"2015-07-30 17:45:00",
            productionItemId: null,
            shiftDuration: 30, 
        }, 
        initialize: function(){
            _.bindAll(this); 

            this.attributes.productionItem = new OEE.Models.ProductionItem();
            this.attributes.delaysInformation = new OEE.Models.DelaysInformation();

            this.checkFromTo(); 
        },
        checkFromTo: function () {
            var now = app.models.navBarClock.get("date");
            if (!now) {
                app.models.navBarClock.syncWithServer({ async: false });
                now = app.models.navBarClock.get("date");
            }

            now = new Date(now.getTime()); 

            var minutes = now.getMinutes();
            minutes = minutes - (minutes % this.get("shiftDuration")); 

            now.setMinutes(minutes);
            now.setSeconds(0);

            this.set("from", Core.DateTime.ToString(now, "yyyy-mm-dd HH:MM:ss"));
            this.set("to", Core.DateTime.ToString(new Date(now.getTime() + this.get("shiftDuration") * 60000), "yyyy-mm-dd HH:MM:ss"));

            setTimeout(this.checkFromTo, 100); 
        }, 
    });

    //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.
    OEE.generateID = function (viewParams) {
        try {
            //if the viewparams change the view id, then evaluate the viewparams here
            //and return the appropiate id.
            return "delays-2"; 
        } catch (Error) { }
    }

    OEE.Models.ProductionItem = Backbone.Model.extend({
        defaults: {
            id: null,

            oee: null, 
            availability: null,
            quality: null,
            performance: null,

            targetQty: null,
            actualQty: null,

            targetProductionRate: null,
            actualProductionRate: null,

            inMaintenance: null,
        },
        initialize: function () {
            //this.attributes.children = new OEEOverview.Collections.ProductionItems({}); 
        },
        fetch: function (opt) {
            var id = _.isObject(opt) ? opt.id : opt;
            var from = (_.isObject(opt) && opt.from) ? opt.from : null;
            var to = (_.isObject(opt) && opt.to) ? opt.to : null;

            id = (id) ? id : null;

            var that = this;
            var QP = new Core.Database.QueryParameters();

            QP.Add("ProductionItemId", "INT", id);
            QP.Add("From", "DATETIME", from);
            QP.Add("To", "DATETIME", to);
            QP.Add("Timezone", "VARCHAR", app.models.user.get("timezoneCode"));

            Core.Json.CallProcedure(app.DatabaseNames.OEE + ".WebApp.GetOEE", QP, {
                onSuccess: function (data) {
                    if (data && data.Table) {
                        var oeeData = data.Table[0];
                        var productionData = data.Table1[0]; 

                        var productionItemModel = _.extend({}, that.attributes, {
                            id: oeeData.Id,

                            oee: oeeData.OEE,
                            availability: oeeData.Availability,
                            quality: oeeData.Quality,
                            performance: oeeData.Performance,

                            targetQty: productionData.TargetQuantity,
                            actualQty: productionData.ActualQuantity,
                            targetProductionRate: productionData.TargetProductionRate,
                            actualProductionRate: productionData.ActualProductionRate,

                            inMaintenance: productionData.InMaintenance, 
                        });

                        that.set(productionItemModel, { from: "fetch" });
                    }
                },
                Secured: true,
            }, app.ConnectionStrings.app);
        },
    });

    OEE.Models.Delay = Backbone.Model.extend({
        defaults: {
            id: null,
            delayCodeId: null,
            delayCodeParentId: null, 
            start: null,
            end: null,
            duration: null, 
        }
    });

    OEE.Models.DelayCode = Backbone.Model.extend({
        defaults: {
            id: null,
            code: null,
            description: null,
            color: null, 
        },
    }); 

    OEE.Models.TimeAccount = Backbone.Model.extend({
        defaults: {
            id: null,
            code: null,
            category: null,
            description: null,
            color: null,
            duration: null,
            lastUpdate: 0,
        }
    });

    OEE.Collections.Delays = Backbone.Collection.extend({
        model: OEE.Models.Delay,
    }); 

    OEE.Collections.TimeAccounts = Backbone.Collection.extend({
        model: OEE.Models.TimeAccount, 
    }); 

    OEE.Collections.DelayCodes = Backbone.Collection.extend({
        model: OEE.Models.DelayCode, 
    }); 

    OEE.Models.DelaysInformation = Backbone.Model.extend({
        defaults: {
            delays: null,
            timeAccounts: null,
            delayCodes: null, 
        },

        refreshCount: 0,

        initialize: function () {
            this.attributes.delays = new OEE.Collections.Delays();
            this.attributes.timeAccounts = new OEE.Collections.TimeAccounts();
            this.attributes.delayCodes = new OEE.Collections.DelayCodes();
        }, 
        fetch: function (opt) {
            var id = _.isObject(opt) ? opt.id : opt;
            id = (id) ? id : null;

            var from = (_.isObject(opt) && opt.from) ? opt.from : null;
            var to = (_.isObject(opt) && opt.to) ? opt.to : null;

            var that = this;
            var QP = new Core.Database.QueryParameters();

            QP.Add("ProductionItemId", "INT", id);
            QP.Add("From", "DATETIME", from);
            QP.Add("To", "DATETIME", to);
            QP.Add("Timezone", "VARCHAR", app.models.user.get("timezoneCode"));

            Core.Json.CallProcedure(app.DatabaseNames.OEE + ".WebApp.GetDelayEvents", QP, {
                onSuccess: function (data) {
                    if (data && data.Table) {
                        var delays = data.Table;
                        var timeaccounts = data.Table1;
                        var delayCodes = data.Table2; 
                        
                        var delayModelsArr = []; 
                        for (var i = 0; i < delays.length; i++) {
                            var delayModel = new OEE.Models.Delay({
                                id: (delays[i].Id != -2) ? delays[i].Id : null,
                                delayCodeId: delays[i].DelayCodeId,
                                delayCodeParentId: delays[i].DelayCodeParentId,
                                start: delays[i].Start,
                                end: delays[i].End,
                                duration: delays[i].Duration,
                            });

                            delayModelsArr.push(delayModel); 
                        }

                        var timeAccountModelsArr = [],
                            totalDuration = 0; 
                        for (var i = 0; i < timeaccounts.length; i++) {
                            var timeaccountModel = new OEE.Models.TimeAccount({
                                id: timeaccounts[i].Id,
                                code: timeaccounts[i].Code,
                                category: timeaccounts[i].Category,
                                description: timeaccounts[i].Description,
                                color: timeaccounts[i].Color,
                                duration: timeaccounts[i].Duration,
                            });

                            totalDuration += timeaccounts[i].Duration;

                            timeAccountModelsArr.push(timeaccountModel); 
                        }

                        var totalTimeaccountModel = new OEE.Models.TimeAccount({
                            id: -2,
                            code: 'Total',
                            category: '',
                            description: '',
                            color: '',
                            duration: totalDuration,
                            isTotal: true,
                            lastUpdate: ++that.refreshCount,
                        });

                        timeAccountModelsArr.push(totalTimeaccountModel);



                        var delayCodesArr = [];
                        for (var i = 0; i < delayCodes.length; i++) {
                            var delayCodeModel = new OEE.Models.DelayCode({
                                id: delayCodes[i].Id,
                                code: delayCodes[i].Code,
                                description: delayCodes[i].Description,
                                color: delayCodes[i].Color,
                            });

                            delayCodesArr.push(delayCodeModel); 
                        }

                        var notDeclared = new OEE.Models.DelayCode({
                            id: -1,
                            code: "NOTDECLARED",
                            description: "Not Declared",
                            color: "#de2e27",
                        }); 

                        delayCodesArr.push(notDeclared);

                        //var total = new OEE.Models.DelayCode({
                        //    id: -2,
                        //    code: "Total",
                        //    //description: "",
                        //    //color: "#de2e27",
                        //});

                        //delayCodesArr.push(total);

                        that.get("delays").set(delayModelsArr);
                        that.get("timeAccounts").set(timeAccountModelsArr);
                        that.get("delayCodes").set(delayCodesArr); 
                    }
                },
                Secured: true,
            }, app.ConnectionStrings.app);
        }, 
    }); 

    OEE.Views.Main = Backbone.View.extend({
        template: "delays-2"
        , id: "delays-2"
        , title: "Delays2"
        //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
        , initialize: function () {
            this.options.state = app.view_states.loading;
            this.options.onappend = (_.isFunction(this.options.onappend)) ? this.options.onappend : function () { };

            var productionItemId = null;

            if (this.options.viewParams) {
                productionItemId = (this.options.viewParams.id != null && this.options.viewParams.id != undefined)
                    ? this.options.viewParams.id : this.model.get('productionItemId');
            }

            var model = new OEE.Models.Main({
                productionItemId: productionItemId, 
            });

            this.options.MYREFERENCES = {
                subviews: {
                }
                , autoRefresh: {
                    enabled: true
                    , toid: null
                },
                isRendering: false,
                isRendered: false, 
            };

            this.options.graph = {
                productQty: {
                    progressbars: {
                        actual: null,
                        target: null,
                        options: null, 
                    }
                },
                oee: {
                    circleProgress: {
                        oee: null,
                        ava: null,
                        per: null,
                        qua: null, 
                    }
                },
                halfCircle: {},
                events: {
                    grid: null,
                    collection: null,
                    model: null,
                    col: null,
                },
                timeAccounts: {
                    grid: null,
                    collection: null,
                    model: null,
                    col: null,
                }
            }; 

            this.model = model;

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

        events: {
        }, 

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

            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.oeeModule.screensPath + "delays/delays-2/";
            if (this.model.get("productionItem").get("id")) {
                this.options.MYREFERENCES.isRendering = true; 
                T.render.call(this, this.template, function (tmp) {
                    //getInternationalizationData
                    if (!that.options.i18n) that.options.i18n = {};
                    app.getI18NJed(that, that.template, function (i18nJED) {
                        //storing internationalization data
                        that.options.i18n[that.template] = i18nJED;

                        var productionItem = that.model.get("productionItem");
                        that.$el.html(tmp(productionItem.toJSON()));
                        that.append(thatContainer, that.$el);

                        setTimeout(that.drawCircles, 1000);

                        that.renderTimeAccountsGrid();
                        that.drawProgressGraph();
                        that.renderEventsGrid();

                        that.options.MYREFERENCES.isRendering = false;
                        that.options.MYREFERENCES.isRendered = true;
                    }, true, customPath);
                }, customPath, "main_template");
            } else {
                this.$el.html('<div style="text-align:center;margin-top:10px;font-size:24px;"><i class="fa fa-5x fa-cog fa-spin"></i><br />Loading ...</div>');
                this.append(thatContainer, this.$el);
            }

            if (!this.options.MYREFERENCES.isRendered)
                this._startAutoRefresh();
        }

        , _getPercent: function (val, opt){
            return (Math.round((val * 100) / opt.total)) / 100;
        }
        , _sign: function (num) {
            // IE does not support method sign here
            if (typeof Math.sign === 'undefined') {
                if (num > 0) {
                    return 1;
                }
                if (num < 0) {
                    return -1;
                }
                return 0;
            }
            return Math.sign(num);
        }
        , precise_round: function (num, decimals) {
            var t = Math.pow(10, decimals);
            return (Math.round((num * t) + (decimals > 0 ? 1 : 0) * (this._sign(num) * (10 / Math.pow(100, decimals)))) / t).toFixed(decimals);
        }
        , _getValue: function (perc, opt, topVal) {
            topVal = _.isNumber(topVal) ? topVal : null
            var val = this.precise_round((perc * opt.total) / 100, 2);
            val = parseFloat(val);
            val = (val > 1) ? Math.round(val) : val;
            val = (val * 100).toFixed(0);
            return (topVal == null || val <= topVal) ? val : topVal;
        }
        , renderEventsGrid: function () {
            var that = this; 
            var eventModel = Backbone.Model.extend({
                defaults: {
                    id: null,
                    start: null,
                    end: null,
                    duration: null,
                    cause: null,
                    detail: null, 
                },
            });

            var eventsCollection = Backbone.Collection.extend({
                model: eventModel,
            }); 

            this.options.graph.events.model = eventModel;
            this.options.graph.events.col = eventsCollection; 

            var events = this.options.graph.events.collection = new eventsCollection();
            
            var columns = [
                {
                    name: "start",
                    label: "Start",
                    editable: false,
                    cell: Backgrid.StringCell.extend({
                        orderSeparator: '',
                        className: "string-cell",
                    })
                },
                {
                    name: "end",
                    label: "End",
                    editable: false,
                    cell: Backgrid.StringCell.extend({
                        orderSeparator: '',
                        className: "string-cell",
                    })
                },
                {
                    name: "duration",
                    label: "Duration",
                    editable: false,
                    cell: Backgrid.StringCell.extend({
                        orderSeparator: '',
                        className: "string-cell",
                        render: function () {
                            this.$el.html(this.secondsToHHMMSS(this.model.get("duration")));
                            this.delegateEvents();
                            return this;
                        },
                        secondsToHHMMSS: function (d) {
                            d = Number(d);
                            var h = Math.floor(d / 3600);
                            var m = Math.floor(d % 3600 / 60);
                            var s = Math.floor(d % 3600 % 60);
                            return ((h > 0 ? h + ":" + (m < 10 ? "0" : "") : "") + m + ":" + (s < 10 ? "0" : "") + s);
                        },
                    })
                },
                {
                    name: "cause",
                    label: "Cause",
                    editable: false,
                    cell: Backgrid.StringCell.extend({
                        orderSeparator: '',
                        className: "string-cell",
                    })
                },
                {
                    name: "details",
                    label: "Details",
                    editable: false,
                    cell: Backgrid.StringCell.extend({
                        orderSeparator: '',
                        className: "string-cell",
                    })
                },
            ];

            var grid = new Backgrid.Grid({
                className: "backgrid table table-hover",
                columns: columns,
                collection: events,
            });

            this.$el.find(".events-grid-container").append(grid.render().el);
            this.refreshEventsGrid(); 
        }
        , timeAccountsChart: function () {

            var that = this;

            var ta_table = this.$el.find(".time-accounts-table");
            var ts = ta_table.find("[data-time-progressbar]");

            var opt = {
                total: 0
            };

            ts.each(function () { opt.total += $(this).data("time-progressbar-value"); });

            ts.each(function () {
                var tr = $(this);
                var pbar_container = tr.find(".time-progressbar-container");
                var val = tr.data("time-progressbar-value");

                var pbar = new ProgressBar.Line(pbar_container.get(0), {
                    color: "#CCCCCC",
                    trailColor: 'transparent',
                    trailWidth: 1,
                    easing: 'easeInOut',
                    strokeWidth: 10,
                    step: function (state, bar) {
                    }
                });

                pbar.animate(that._getPercent(val, opt));
            });

        }

        , refreshEventsGrid: function () {
            var that = this;
            var events = this.options.graph.events.collection;
            var eventModel = this.options.graph.events.model;

            var eventsArr = [];
            this.model.get("delaysInformation").get("delays").filter(function (m) {
                return m.id != null;
            }).forEach(function (m) {
                var delayCode = that.model.get("delaysInformation").get("delayCodes").findWhere({ id: m.get("delayCodeId") });
                if (!delayCode) delayCode = that.model.get("delaysInformation").get("delayCodes").findWhere({ id: -1 });

                eventsArr.push(new eventModel({
                    id: m.get("id"),
                    start: m.get("start"),
                    end: m.get("end"),
                    duration: m.get("duration"),
                    cause: (delayCode) ? delayCode.get("code") : null,
                    detail: (delayCode) ? delayCode.get("description") : null,
                }));
            });

            events.reset(eventsArr);
        }

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

            // Arc layout
            $.circleProgress.defaults.arcCoef = 1; // default; range: 0..1
            $.circleProgress.defaults.startAngle = -1.5 * Math.PI; // default

            $.circleProgress.defaults.drawArc = function (v) {
                var ctx = this.ctx,
                    r = this.radius,
                    t = this.getThickness(),
                    c = this.arcCoef,
                    a = this.startAngle + (1 - c) * Math.PI;

                v = Math.max(0, Math.min(1, v));

                ctx.save();
                ctx.beginPath();

                if (!this.reverse) {
                    ctx.arc(r, r, r - t / 2, a, a + 2 * c * Math.PI * v);
                } else {
                    ctx.arc(r, r, r - t / 2, a + 2 * c * Math.PI, a + 2 * c * (1 - v) * Math.PI, a);
                }

                ctx.lineWidth = t;
                ctx.lineCap = this.lineCap;
                ctx.strokeStyle = this.arcFill;
                ctx.stroke();
                ctx.restore();
            };

            $.circleProgress.defaults.drawEmptyArc = function (v) {
                var ctx = this.ctx,
                    r = this.radius,
                    t = this.getThickness(),
                    c = this.arcCoef,
                    a = this.startAngle + (1 - c) * Math.PI;

                v = Math.max(0, Math.min(1, v));

                if (v < 1) {
                    ctx.save();
                    ctx.beginPath();

                    if (v <= 0) {
                        ctx.arc(r, r, r - t / 2, a, a + 2 * c * Math.PI);
                    } else {
                        if (!this.reverse) {
                            ctx.arc(r, r, r - t / 2, a + 2 * c * Math.PI * v, a + 2 * c * Math.PI);
                        } else {
                            ctx.arc(r, r, r - t / 2, a, a + 2 * c * (1 - v) * Math.PI);
                        }
                    }

                    ctx.lineWidth = t;
                    ctx.strokeStyle = this.emptyFill;
                    ctx.stroke();
                    ctx.restore();
                }
            };

            this.$el.find(".circle").each(function () {
                var $circle = $(this);
                var val = $circle.data("circle-value");
                var circle_container = $circle.parent(".circle-container");
                var circle_gradient = ($circle.data("circle-gradient")) ? $circle.data("circle-gradient") : ['#29D65A', '#29D67D'];
                var circle_thickness = ($circle.data("circle-thickness")) ? $circle.data("circle-thickness") : 25;
                var circle_size = ($circle.data("circle-size")) ? $circle.data("circle-size") : 80;
                var circle_name = $circle.data("circle-name");
                var size = (circle_size * circle_container.width()) / 100;

                that.options.graph.oee.circleProgress[circle_name] = $circle;

                that.options.graph.oee.circleProgress[circle_name].circleProgress({
                    value: (val) ? val / 100 : 0,
                    size: size,
                    startAngle: -Math.PI / 4 * 2,
                    thickness: circle_thickness,
                    fill: {
                        gradient: circle_gradient,
                    }
                });

                that.options.graph.oee.circleProgress[circle_name].on("circle-animation-progress", function (event, progress, stepValue) {
                    var progress_display = $circle.find(".progress-display");
                    if (progress_display.length > 0) {
                        progress_display.text((stepValue * 100).toFixed(0) + "%");
                    }
                });
            });

            var halfcircle_opt = {
                total: this.model.get("productionItem").get("targetProductionRate") + 5,
            };

            this.$el.find(".half-circle").each(function () {
                var $half_circle = $(this);
                var val = $half_circle.data("circle-value");
                var circle_container = $half_circle.parent(".circle-container");
                var circle_size = ($half_circle.data("circle-size")) ? $half_circle.data("circle-size") : 80;
                var circle_thickness = ($half_circle.data("circle-thickness")) ? $half_circle.data("circle-thickness") : 25;
                var circle_name = $half_circle.data("circle-name");
                var size = (circle_size * circle_container.width()) / 100;

                that.options.graph.halfCircle[circle_name] = { graph: null, opts: null };
                that.options.graph.halfCircle[circle_name].graph = $half_circle;
                that.options.graph.halfCircle[circle_name].opts = halfcircle_opt;

                that.options.graph.halfCircle[circle_name].graph.circleProgress({
                    value: that._getPercent(val, halfcircle_opt),
                    size: size,
                    thickness: circle_thickness,
                    arcCoef: 0.5,
                    fill: {
                        gradient: ["#ecee12", "#258A3D"],
                    },
                    initWidget: function () {
                        var canvas = this.canvas = this.canvas || $('<canvas>').prependTo(this.el)[0];
                        canvas.width = this.size;
                        canvas.height = this.size / 2;
                        this.ctx = canvas.getContext('2d');
                    },
                }).on("circle-animation-progress", function (event, progress, stepValue) {
                    var progress_display = that.$el.find(".half-circle-progress-display");
                    if (progress_display.length > 0) {
                        progress_display.text(that._getValue(stepValue, halfcircle_opt));
                    }
                });
            });

            var progressbarset_options = {
                total: this.model.get("productionItem").get("targetQty") + 50,
                actual: this.model.get("productionItem").get("actualQty"),
                target: this.model.get("productionItem").get("targetQty"),
            };

            this.options.graph.productQty.progressbars.options = progressbarset_options;

            var progressbar_actual = this.options.graph.productQty.progressbars.actual = new ProgressBar.Line('.progressbar-actual', {
                color: "#ff0000",
                trailColor: 'transparent',
                trailWidth: 1,
                easing: 'easeInOut',
                strokeWidth: 4,
                //from: { color: '#FFF' },
                //to: { color: '#ff0000' },
                //step: function (state, bar) {
                //    bar.path.setAttribute('stroke', state.color);
                //    that.$el.find(".actual-qty-display").text(that._getValue(bar.value(), progressbarset_options, progressbarset_options.actual));
                //}
            });

            var progressbar_target = this.options.graph.productQty.progressbars.target = new ProgressBar.Line('.progressbar-target', {
                color: "#CCCCCC",
                trailColor: 'transparent',
                trailWidth: 1,
                easing: 'easeInOut',
                strokeWidth: 4,
                from: { color: '#FFF' },
                to: { color: '#CCCCCC' },
                step: function (state, bar) {
                    bar.path.setAttribute('stroke', state.color);
                    that.$el.find(".target-qty-display").text(that._getValue(bar.value(), progressbarset_options, progressbarset_options.target));
                }
            });

            progressbar_target.animate(that._getPercent(progressbarset_options.target, progressbarset_options), function () {
                that.$el.find(".target-qty-display").text(progressbarset_options.target);
                progressbar_actual.animate(that._getPercent(progressbarset_options.actual, progressbarset_options), function () {
                    that.$el.find(".actual-qty-display").text(progressbarset_options.actual);
                });
            });
        }

        , renderTimeAccountsGrid: function () {
            var that = this;
            var timeAccountModel = Backbone.Model.extend({
                defaults: {
                    name: null,
                    duration: null,
                    color: null,
                    category: null,
                    isTotal: false,
                },
            });

            this.options.graph.timeAccounts.model = timeAccountModel;

            var timeAccountsCollection = Backbone.Collection.extend({
                model: timeAccountModel,
            });

            this.options.graph.timeAccounts.col = timeAccountsCollection;

            var timeAccounts = new timeAccountsCollection();

            this.options.graph.timeAccounts.collection = timeAccounts;

            var total = (Core.DateTime.Parse(this.model.get("to"))).getTime() - (Core.DateTime.Parse(this.model.get("from"))).getTime();
            total = total / 1000;
            var opt = {
                total: total,
            };

            //timeAccounts.forEach(function (m) { opt.total += m.get("duration"); });
            //timeAccounts.add({ name: "Staffed Time", duration: opt.total, color: '#ccc' }); 

            var columns = [
                {
                    name: "name",
                    label: app.translate(that, "name_label"),
                    editable: false,
                    cell: Backgrid.StringCell.extend({
                        orderSeparator: '',
                        className: "string-cell",
                    })
                },
                {
                    name: "category",
                    label: app.translate(that, "category_label"),
                    editable: false,
                    cell: Backgrid.StringCell.extend({
                        orderSeparator: '',
                        className: "string-cell",
                    })
                },
                {
                    name: "duration",
                    label: app.translate(that, "duration_label"),
                    editable: false,
                    cell: Backgrid.StringCell.extend({
                        orderSeparator: '',
                        className: "string-cell",
                        render: function () {
                            this.$el.html(this.secondsToHHMMSS(this.model.get("duration")));
                            this.delegateEvents();
                            return this;
                        },
                        secondsToHHMMSS: function (d) {
                            d = Number(d);
                            var h = Math.floor(d / 3600);
                            var m = Math.floor(d % 3600 / 60);
                            var s = Math.floor(d % 3600 % 60);
                            return ((h > 0 ? h + ":" + (m < 10 ? "0" : "") : "") + m + ":" + (s < 10 ? "0" : "") + s);
                        },
                    })
                },
                {
                    name: "graph",
                    label: app.translate(that, "graph_label"),
                    editable: false,
                    cell: Backgrid.StringCell.extend({
                        template: _.template("<div style='height:20px;width:180px;position:relative;' class='bar-graph-container'></div>"),
                        orderSeparator: '',
                        className: "string-cell",
                        initialize: function () {
                            _.bindAll(this);
                            Backgrid.StringCell.prototype.initialize.apply(this, arguments);

                            this.options.graph = {
                                pbar: null,
                            };

                            this.bindEvents();
                        },
                        render: function () {
                            this.$el.html(this.template());
                            var pbar_container = this.$el.find(".bar-graph-container");

                            if (this.model.get("isTotal") == false) {
                                var val = this.model.get("duration");

                                var pbar = this.options.graph.pbar = new ProgressBar.Line(pbar_container.get(0), {
                                    color: this.model.get("color"),
                                    trailColor: 'transparent',
                                    easing: 'easeInOut',
                                    step: function (state, bar) {
                                    }
                                });

                                pbar_container.find("svg").css({
                                    height: "20px",
                                    width: "100%",
                                    "overflow-y": "hidden",
                                });

                                setTimeout(function () {
                                    pbar.animate(that._getPercent(val, opt));
                                }, 1000);
                            }
                            else {
                                var that2 = this;
                                that2.options.graph.pbar = [];

                                timeAccounts.each(function (timeModel, imodel) {
                                    var val = timeModel.get("duration");

                                    var pbar = new ProgressBar.Line(pbar_container.get(0), {
                                        color: timeModel.get("color"),
                                        trailColor: 'transparent',
                                        easing: 'easeInOut',
                                        step: function (state, bar) {
                                        }
                                    });

                                    that2.options.graph.pbar.push(pbar);

                                    $(pbar_container.find("svg")[imodel]).css({
                                        height: "20px",
                                        //width: "100%",
                                        width: (that._getPercent(val, opt) * 100) + "%",
                                        "overflow-y": "hidden",
                                        "float": "left",
                                    });

                                    setTimeout(function () {
                                        //pbar.animate(that._getPercent(val, opt));
                                        pbar.animate(1);
                                    }, 1000);
                                });
                            }

                            this.delegateEvents();
                            return this;
                        },
                        refresh: function () {
                            if (this.model.get("isTotal") == false) {
                                var val = this.model.get("duration");
                                this.options.graph.pbar.animate(that._getPercent(val, opt));
                            }
                            else {
                                var that2 = this;
                                var graphList = this.$el.find(".bar-graph-container").find("svg");

                                timeAccounts.each(function (timeModel, imodel) {
                                    var val = timeModel.get("duration");
                                    graphList[imodel].css({
                                        width: (that._getPercent(val, opt) * 100) + "%",
                                    });
                                    that2.options.graph.pbar[imodel].animate(1);
                                });
                            }
                        },
                        refreshUpdate: function () {
                            if (this.model.get("isTotal") == true) {
                                var that2 = this;
                                var graphList = this.$el.find(".bar-graph-container").find("svg");

                                timeAccounts.each(function (timeModel, imodel) {
                                    var val = timeModel.get("duration");
                                    graphList[imodel].css({
                                        width: (that._getPercent(val, opt) * 100) + "%",
                                    });

                                    setTimeout(function () {
                                        that2.options.graph.pbar[imodel].animate(1);
                                    }, 1000);

                                });
                            }
                        },
                        bindEvents: function () {
                            this.listenTo(this.model, "change", this.refresh);
                            this.listenTo(this.model, "change:lastUpdate", this.refreshUpdate);
                        },
                    })
                },
            ];

            var grid = new Backgrid.Grid({
                className: "backgrid table table-hover table-condensed",
                columns: columns,
                collection: timeAccounts,
            });

            this.options.graph.timeAccounts.grid = grid;

            this.$el.find(".time-accounts-grid-container").append(grid.render().el);

            this.refreshTimeAccountsGrid();
        }
        , refreshTimeAccountsGrid: function () {
            var timeAccounts = this.options.graph.timeAccounts.collection;

            var timeaccountsarr = [];
            this.model.get("delaysInformation").get("timeAccounts").forEach(function (m) {
                timeaccountsarr.push({
                    id: m.get("id"),
                    name: m.get("code"),
                    duration: m.get("duration"),
                    color: m.get("color"),
                    category: m.get("category"),
                    isTotal: m.get("isTotal"),
                    lastUpdate: m.get("lastUpdate"),
                });
            });

            timeAccounts.set(timeaccountsarr);
        }
        , drawProgressGraph: function () {
            var that = this;

            //total in seconds
            var total = (Core.DateTime.Parse(this.model.get("to"))).getTime() - (Core.DateTime.Parse(this.model.get("from"))).getTime();
            total = total / 1000;
            var opt = {
                total: total,
            };

            var itemCategory = Backbone.Model.extend({
                defaults: {
                    id: null,
                    name: null,
                    color: null,
                },
            });

            var itemCategoriesCollection = Backbone.Collection.extend({
                model: itemCategory,
            });

            var itemCategories = new itemCategoriesCollection();
            itemCategories.add(new itemCategory({
                id: -2,
                name: "Active",
                colorCode: "#3aea3a",
                color: "#3aea3a",
            }));
            itemCategories.add(new itemCategory({
                id: -1,
                name: "Not Declared",
                colorCode: "#de2e27",
                color: "red",
            }));

            this.model.get("delaysInformation").get("delayCodes").forEach(function (m) {
                var color = (_.isString(m.get("color"))) ? m.get("color").trim() : "";
                switch (color.toUpperCase()) {
                    case "#DE2E27":
                        color = "red";
                        break;
                    case "#3AEA3A":
                        color = "green";
                        break;
                    case "#15A1CB":
                        color = "blue";
                        break;
                    case "#ECEE12":
                        color = "yellow";
                        break;
                    case "#FFAE00":
                        color = "orange";
                    case "#0088FF":
                        color = "light-blue";
                        break;
                }

                itemCategories.add(
                    new itemCategory({
                        id: m.get("id"),
                        name: m.get("code"),
                        colorCode: m.get("color"),
                        color: color, 
                    })
                );
            }); 

            var progressItemModel = Backbone.Model.extend({
                defaults: {
                    duration: null,
                    category: null,
                    start: null,
                    end: null, 
                },
            });

            var progressItemsCollection = Backbone.Collection.extend({
                model: progressItemModel,
            });

            var progressItems = new progressItemsCollection(); 

            var delays = this.model.get("delaysInformation").get("delays");
            //var firstDelayStart; 
            
            //var now = app.models.navBarClock.get("date");
            //if (!now) {
            //    app.models.navBarClock.syncWithServer({ async: false });
            //    now = app.models.navBarClock.get("date");
            //}
            //now = new Date(now.getTime()); 

            //if (delays.length > 0) {
            //    firstDelayStart = delays.at(0).get("start");
            //} else {
            //    if (now > this.model.get("to")) firstDelayStart = new Date(this.model.get("to").getTime()); 
            //    else firstDelayStart = now; 

            //    firstDelayStart = Core.DateTime.ToString(firstDelayStart, "yyyy-mm-dd HH:MM:ss");
            //}

            //var date1 = Core.DateTime.Parse(firstDelayStart); 
            //var date2 = Core.DateTime.Parse(this.model.get("from"));
            //var diff = Math.abs(date1.getTime() - date2.getTime()); 
            //diff = diff / 1000; 

            //progressItems.add(new progressItemModel({
            //    duration: diff,
            //    category: itemCategories.findWhere({ id: -1 }), 
            //})); 

            delays = this.model.get("delaysInformation").get("delays").sortBy(function (m) {
                return m.get("start");
            }); 

            delays.forEach(function (m, inx) {
                var pim = new progressItemModel({
                    id: m.get("id"), 
                    duration: m.get("duration"),
                    start: m.get("start"),
                    end: m.get("end"), 
                    category: itemCategories.findWhere({ id: m.get("delayCodeParentId") }),
                });

                if (!pim.get("category")) {
                    if (!m.get("id")) {
                        pim.set("category", itemCategories.findWhere({ id: -2 }));
                    } else {
                        pim.set("category", itemCategories.findWhere({ id: -1 }));
                    }
                }

                progressItems.add(pim); 
                //if ((inx + 1) < delays.length) {
                //    var nextDelay = delays.at(inx + 1);
                //    var d1 = Core.DateTime.Parse(m.get("end"));
                //    var d2 = Core.DateTime.Parse(nextDelay.get("start"));
                //    var df = Math.abs(d1.getTime() - d2.getTime());
                //    df = df / 1000;

                //    progressItems.add(new progressItemModel({
                //        duration: df,
                //        category: itemCategories.findWhere({ id: -1 }),
                //    }));
                //} else {
                //    var next; 
                //    if (now > Core.DateTime.Parse(that.model.get("to"))) next = new Date(Core.DateTime.Parse(that.model.get("to")).getTime());
                //    else next = now;

                //    var d1 = Core.DateTime.Parse(m.get("end"));
                //    var d2 = Core.DateTime.Parse(next);
                //    var df = Math.abs(d1.getTime() - d2.getTime());
                //    df = df / 1000;

                //    progressItems.add(new progressItemModel({
                //        duration: df,
                //        category: itemCategories.findWhere({ id: -1 }),
                //    }));
                //}
            }); 

            var container = this.$el.find(".progress-bar-container");
            var pbar = container.find(".progress"); 
            pbar.empty(); 

            var totalwd = 0; 
            progressItems.forEach(function (m) {
                var bar = $("<div style='cursor:pointer;' class='bar bar-popover bar-hover'></div>")
                var wd = (that._getPercent(m.get("duration"), opt) * 100);

                while ((totalwd + wd) > 100) {
                    wd--; 
                }
                totalwd += wd; 

                if (m.get("category").get("name").toUpperCase() != "ACTIVE") {
                    //bar.width(wd + "%");
                    bar.addClass("bar-" + m.get("category").get("color"));

                    var popover_title = _.template('<h4 style="color: #fff;padding:0px;"><%= title %></h4>');
                    var popover_content = _.template('<div><dl class="dl-horizontal">'
                                            + '<dt style="width:100px;">Reason</dt><dd style="margin-left:120px;"><%= reason %></dd>'
                                            + '<dt style="width:100px;">Start Time</dt><dd style="margin-left:120px;"><%= startTime %></dd>'
                                            + '<dt style="width:100px;">Duration</dt><dd style="margin-left:120px;"><%= duration %></dd>'
                                            + '</dl></div>');

                    //creating popover
                    var mod = that.model.get("delaysInformation").get("delays").findWhere({ id: m.get("id") });

                    var $po = bar.popover({
                        placement: "top",
                        html: true,
                        trigger: "hover",
                        title: popover_title({ title: m.get("category").get("name") }),
                        content: popover_content({ reason: m.get("category").get("name"), startTime: m.get("start"), duration: m.get("duration") }),
                        delay: { show: 150, hide: 0 },
                    });

                    $po.on("shown", function () {
                        pbar.find(".popover-title").css({ "background-color": m.get("category").get("colorCode") });
                    });

                    bar.css("width", wd + "%");
                    pbar.append(bar);

                    //setTimeout(function () {
                    //    bar.animate({ width: wd + "%" }); 
                    //}, 1000); 
                }
                else
                {
                    bar.css({ width: wd + "%", visibility: "hidden", });
                    pbar.append(bar);
                }
            }); 

        }

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

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

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

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

            this.refresh();

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

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

        , preExecRender: function () {
            var rendered = this.options.MYREFERENCES.isRendered;
            var rendering = this.options.MYREFERENCES.isRendering; 

            if (!rendered && !rendering) this.render();
            else if (!rendering) this.refreshGraph();
            else setTimeout(this.preExecRender, 100); 
        }
        , refreshGraph: function () {
            try{
                var that = this;

                this.options.graph.oee.circleProgress["oee"].circleProgress('value', this.model.get("productionItem").get("oee") / 100);
                this.options.graph.oee.circleProgress["ava"].circleProgress('value', this.model.get("productionItem").get("availability") / 100);
                this.options.graph.oee.circleProgress["per"].circleProgress('value', this.model.get("productionItem").get("performance") / 100);
                this.options.graph.oee.circleProgress["qua"].circleProgress('value', this.model.get("productionItem").get("quality") / 100);

                this.options.graph.halfCircle["productionRate"].graph.circleProgress('value', this._getPercent(this.model.get("productionItem").get("actualProductionRate"), this.options.graph.halfCircle["productionRate"].opts));

                var progressbar_target = this.options.graph.productQty.progressbars.target;
                var progressbar_actual = this.options.graph.productQty.progressbars.actual;

                var progressbarset_options = this.options.graph.productQty.progressbars.options; 
                progressbarset_options.actual = this.model.get("productionItem").get("actualQty");

                var inMaintenance = this.$el.find(".in-maintenance-icon");
                var inMaintenance_val = this.model.get("productionItem").get("inMaintenance"); 
                var inMaintenance_class = (inMaintenance_val == false) ? "green-mode" : (inMaintenance_val == true) ? "red-mode" : "yellow-mode"; 
                inMaintenance.removeClass("green-mode").removeClass("red-mode").removeClass("yellow-mode").addClass(inMaintenance_class); 

                //progressbar_target.animate(that._getPercent(progressbarset_options.target, progressbarset_options), function () {
                //    that.$el.find(".target-qty-display").text(progressbarset_options.target);
                progressbar_actual.animate(that._getPercent(progressbarset_options.actual, progressbarset_options), function () {
                    that.$el.find(".actual-qty-display").text(progressbarset_options.actual);
                });
                //});

                this.drawProgressGraph();
                this.refreshEventsGrid();
                this.refreshTimeAccountsGrid();
            } catch (Error) {
                var e = 1; 
            }
        }
        , refresh: function () {
            try {
                this.model.get("productionItem").fetch({
                    id: this.model.get("productionItemId"),
                    from: this.model.get("from"),
                    to: this.model.get("to"),
                });

                this.model.get("delaysInformation").fetch({
                    id: this.model.get("productionItemId"),
                    from: this.model.get("from"),
                    to: this.model.get("to"),
                }); 
            } catch (Error) { }
        }

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

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

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

                this.options.onappend(this);
            }

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

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

        , bindEvents: function () {
            //this function should be in every view that uses listenTo anywhere
            //all the model bindings or view-model binding should be here, to manage
            //the show/hide view easily
            this.listenTo(this.model.get("productionItem"), "change", this.preExecRender);
        }

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

        , unbindViewScopedEvents: function () {

        }

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

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

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

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

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

        , showSubviews: function () {
            _.each(this.options.MYREFERENCES.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.options.MYREFERENCES.subviews, function (sview) {
                sview.hide();
            });
        }

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

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

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

});

