//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", 

  'moment',

],

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

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

    SendAgentCommands.Models.Main = Backbone.Model.extend({
        defaults: {
            agentId: null,
            dotId: null, 
            commandText: null,
            dotCommandText: null,
            dotmChecked: false, 

            agents: null,
            dots: null, 
            commandTableRows: null, 

            agentsList: [],
            dotsList: [],
        },
        initialize: function () {
            this.attributes.agents = new SendAgentCommands.Collections.Agents();
            this.attributes.dots = new SendAgentCommands.Collections.Dots(); 
            this.attributes.commandTableRows = new SendAgentCommands.Collections.CommandTableRows(); 

            this.listenTo(this.get("agents"), "add", this.parseAgentsList);
            this.listenTo(this.get("agents"), "remove", this.parseAgentsList);
            this.listenTo(this.get("agents"), "reset", this.parseAgentsList);

            this.listenTo(this.get("dots"), "add", this.parseDotsList);
            this.listenTo(this.get("dots"), "remove", this.parseDotsList);
            this.listenTo(this.get("dots"), "reset", this.parseDotsList);
        },
        parseAgentsList: function () {
            this.set({
                agentsList: this.get("agents").map(function (m) {
                    return { value: m.get("id"), label: m.get("name"), };
                }),
            });
        },
        parseDotsList: function () {
            this.set({
                dotsList: this.get("dots").map(function (m) {
                    return { value: m.get("id"), label: m.get("name"), };
                }),
            });
        }
    });

    SendAgentCommands.Models.Dot = Backbone.Model.extend({
        defaults: {
            id: null,
            agentId: null,
            name: null, 
        }, 
    }); 

    SendAgentCommands.Models.Agent = Backbone.Model.extend({
        defaults: {
            id: null,
            name: null,
            type: null,
        },
    }); 

    SendAgentCommands.Models.CommandTableRow = Backbone.Model.extend({
        defaults: {
            id: null, 
            agentId: null,
            agentName: null,
            commandText: null,
            creationTime: null,
            issueTime: null,
            response: null,
            status: null,
            statusChangeTime: null, 
        }
    });

    SendAgentCommands.Collections.Agents = Backbone.Collection.extend({
        model: SendAgentCommands.Models.Agent,
        fetch: function (opt) {
            var options = {
                method: "set",
                async: true,
                callback: null,
            };

            options = _.extend(options, (opt) ? opt : {});

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

            var items = [];

            Core.Json.CallProcedure(app.DatabaseNames.System + ".ACCADMIN.GetAgents", null, {
                onSuccess: function (data) {
                    try
                    {
                        if (Core.Object.Eval(data, "Table")) {
                            var data = data.Table;

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

                                items.push({
                                    id: itemData.Id,
                                    name: itemData.Name,
                                    type: itemData.AgentTypeName, 
                                });
                            }
                        }

                        //var newItems = _.where(that.toJSON(), { isNew: true });
                        //[].push.apply(items, newItems);

                        that[options.method](items, { from: "fetch" });

                        if (options.callback != null && _.isFunction(options.callback))
                            options.callback.call(this, that);
                    }
                    catch (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                },
                Async: options.async,
                Secured: true,
            }, app.ConnectionStrings.app);

            return this;
        },
    }); 

    SendAgentCommands.Collections.CommandTableRows = Backbone.Collection.extend({
        model: SendAgentCommands.Models.CommandTableRow,
        comparator: function (a, b) {
            var ta = new moment(a.get("creationTime"));
            var tb = new moment(b.get("creationTime"));

            if (ta.isBefore(tb)) return 1;
            else if (ta.isAfter(tb)) return -1;
            else return 0;
        },
        fetch: function (opt) {
            var options = {
                method: "set",
                async: true,
                callback: null,
                agents: [], 
            };

            options = _.extend(options, (opt) ? opt : {});

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

            var items = [];

            QP.Add("AgentsId", "VARCHAR", options.agents.join(', '));

            QP.Add("timezone", "VARCHAR", app.models.user.get("timezoneCode"));

            Core.Json.CallProcedure(app.DatabaseNames.System + ".ACCADMIN.GetAgentsCurrentCommands", null, {
                onSuccess: function (data) {
                    if (Core.Object.Eval(data, "Table")) {
                        var data = data.Table;

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

                            items.push({
                                id: itemData.CommandId,
                                agentId: itemData.AgentId,
                                agentName: itemData.AgentName,
                                commandText: itemData.CommandText,
                                creationTime: (itemData.CreationTime)
                                                ? new moment(itemData.CreationTime).format("YYYY-MM-DD HH:mm:ss")
                                                : null,
                                issueTime: (itemData.IssueTime)
                                                ? new moment(itemData.IssueTime).format("YYYY-MM-DD HH:mm:ss")
                                                : null,
                                response: itemData.ResponseText,
                                status: itemData.Status,
                                statusChangeTime: new moment(itemData.StatusChangeTime).format("YYYY-MM-DD HH:mm:ss"),
                            });
                        }
                    }

                    //var newItems = _.where(that.toJSON(), { isNew: true });
                    //[].push.apply(items, newItems);

                    that[options.method](items, { from: "fetch" });

                    if (options.callback != null && _.isFunction(options.callback))
                        options.callback.call(this, that);
                },
                Async: options.async,
                Secured: true,
            }, app.ConnectionStrings.app);

            return this;
        },
    });

    SendAgentCommands.Collections.Dots = Backbone.Collection.extend({
        model: SendAgentCommands.Models.Dot,
        fetch: function (opt) {
            var options = {
                method: "set",
                async: true,
                callback: null,
            };

            options = _.extend(options, (opt) ? opt : {});

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

            var items = [];

            Core.Json.CallProcedure(app.DatabaseNames.System + ".ACCADMIN.GetDashDots", null, {
                onSuccess: function (data) {
                    if (Core.Object.Eval(data, "Table")) {
                        var data = data.Table;

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

                            items.push({
                                id: itemData.Id,
                                agentId: itemData.AgentId,
                                name: itemData.Name, 
                            });
                        }
                    }

                    //var newItems = _.where(that.toJSON(), { isNew: true });
                    //[].push.apply(items, newItems);

                    that[options.method](items, { from: "fetch" });

                    if (options.callback != null && _.isFunction(options.callback))
                        options.callback.call(this, that);
                },
                Async: options.async,
                Secured: true,
            }, app.ConnectionStrings.app);

            return this;
        },
    });

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

    SendAgentCommands.Views.Main = Backbone.Epoxy.View.extend({
        template: "send-agent-commands"
        , id: "send-agent-commands"
        , title: "Send Agent Commands"
        //default not cacheable, change this if you want the view to be cacheable
        // if the view is set as cacheable should also have a refresh method to reset the view without erasing the DOM.
        , isCacheable: true
        , initialize: function () {
            this.options.state = app.view_states.loading;
            this.options.onappend = (_.isFunction(this.options.onappend)) ? this.options.onappend : function () { };

            if (this.options.viewParams) {
            }

            this.options.commandsTableAR = true; 
            this.options.commandsTableTOUT = null; 

            var model = new SendAgentCommands.Models.Main({
            });

            this.model = model;

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

        events: {
            "click .btn-send-command": "sendCommand",
            "click .btn-clear-command": "clearCommand",
            
            //dots
            "click .btn-send-dot-command": "sendDotCommand",
            "click .btn-clear-dot-command": "clearDotCommand",
            "click .btn-dot-command": "sendDotButtonCommand",
        }, 

        render: function (container) {
            var that = this;
            var thatContainer = (container != null && container != undefined) ? container : this.options.container;
            this.options.MYREFERENCES = {};

            //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/IHConfiguration/send-agent-commands/";

            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:

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

                    //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")
                    //end

                    var CommandCell = Backgrid.Cell.extend({
                        template: Handlebars.compile(that.$el.find("script#command_cell_template").html()),
                        events: {
                            "click .btn-dropdown-action-option": "actionClicked", 
                        },
                        initialize: function () {
                            Backgrid.Cell.prototype.initialize.apply(this, arguments);

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

                            this.$el.html(this.template({
                                status: this.model.get("status"), 
                            }));

                            this.delegateEvents();
                            return this;
                        },
                        actionClicked: function (e) {
                            var target = $(e.target);
                            var action = target.data("option");

                            if (action == "cmd-cancel") that.cancelCommand(this.model.get("id")); 
                        },
                        bindEvents: function () {
                            this.listenTo(this.model, "change: status", this.render); 
                        }
                    });

                    var columns = [
                        //{
                        //    name: "agentId",
                        //    label: "AgentId",
                        //    editable: false,
                        //    cell: Backgrid.StringCell.extend({
                        //        orderSeparator: '',
                        //        className: "string-cell align-center-cell",
                        //    })
                        //},
                        {
                            name: "agentName",
                            label: "Name",
                            editable: false,
                            cell: Backgrid.StringCell.extend({
                                orderSeparator: '',
                                className: "string-cell align-center-cell",
                            })
                        },
                        //{
                        //    name: "id",
                        //    label: "CommandId",
                        //    editable: false,
                        //    cell: Backgrid.StringCell.extend({
                        //        orderSeparator: '',
                        //        className: "string-cell align-center-cell",
                        //    })
                        //},
                        {
                            name: "commandText",
                            label: "Command Text",
                            editable: false,
                            cell: Backgrid.StringCell.extend({
                                orderSeparator: '',
                                className: "string-cell align-center-cell",
                            })
                        },
                        {
                            name: "creationTime",
                            label: "CreationTime",
                            editable: false,
                            cell: Backgrid.StringCell.extend({
                                orderSeparator: '',
                                className: "string-cell align-center-cell",
                                render: function () {
                                    Backgrid.StringCell.prototype.render.apply(this, arguments);

                                    if (this.model.get(this.column.get('name')) == null)
                                        this.$el.text("...");

                                    return this;
                                },
                            })
                        },
                        {
                            name: "issueTime",
                            label: "IssueTime",
                            editable: false,
                            cell: Backgrid.StringCell.extend({
                                orderSeparator: '',
                                className: "string-cell align-center-cell",
                                render: function () {
                                    Backgrid.StringCell.prototype.render.apply(this, arguments);

                                    if (this.model.get(this.column.get('name')) == null)
                                        this.$el.text("...");

                                    return this;
                                },
                            })
                        },
                        {
                            name: "response",
                            label: "Response",
                            editable: false,
                            cell: Backgrid.StringCell.extend({
                                orderSeparator: '',
                                className: "string-cell align-center-cell response",
                            })
                        },
                        {
                            name: "status",
                            label: "Status",
                            editable: false,
                            cell: Backgrid.StringCell.extend({
                                orderSeparator: '',
                                className: "string-cell align-center-cell",
                            })
                        },
                        {
                            name: "commandCell",
                            label: "",
                            editable: false,
                            cell: CommandCell, 
                        },
                        //{
                        //    name: "statusChangeTime",
                        //    label: "StatusChangeTime",
                        //    editable: false,
                        //    cell: Backgrid.StringCell.extend({
                        //        orderSeparator: '',
                        //        className: "string-cell align-center-cell",
                        //    })
                        //},
                    ]; 

                    var grid; 
                    that.options.commandsGrid = grid = new Backgrid.Grid({
                        className: "backgrid table table-hover",
                        columns: columns,
                        collection: that.model.get("commandTableRows"),
                    });

                    // Render the grid and attach the root to your HTML document
                    that.$el.find(".commands-grid").append(grid.render().el);

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

                    that.refresh();
                    that.refreshCommands(); 
                }, true, customPath); 
            }, customPath);
        }
        , sendCommand: function (e) {
            if (e) e.preventDefault();

            var QP = new Core.Database.QueryParameters();
            QP.Add("AgentsId", "VARCHAR", this.model.get("agentId").toString());
            QP.Add("CommandText", "VARCHAR", this.model.get("commandText"));

            app.CallProcedure(app.DatabaseNames.System + ".ACCADMIN.SendAgentsCommand", QP, {
                onSuccess: function (data) {
                    app.views.topMessages.showMessage("Command sent."); 
                },
                Secured: true, 
            }, app.ConnectionStrings.app);
        }
        , sendDotCommand: function (e, command, ignoreDOTM) {
            if (e) e.preventDefault();

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

            var d = this.model.get("dots").findWhere({ id: this.model.get("dotId") }); 

            if (d != null) {
                QP.Add("AgentsId", "VARCHAR", d.get("agentId").toString());
                var command = ((this.model.get("dotmChecked") && !ignoreDOTM) ? "DOTM " : "DOT ")
                    + d.get("name") + " " + ((command) ? command : this.model.get("dotCommandText"));
                QP.Add("CommandText", "VARCHAR", command);

                app.CallProcedure(app.DatabaseNames.System + ".ACCADMIN.SendAgentsCommand", QP, {
                    onSuccess: function (data) {
                        app.views.topMessages.showMessage("Command sent.");
                    },
                    Secured: true,
                }, app.ConnectionStrings.app);
            }
        }
        , sendDotButtonCommand: function (e) {
            var target = $(e.target);
            var commandText = target.data("command-text");
            if (_.isString(commandText) && commandText.length > 0) {
                this.sendDotCommand(null, commandText, true); 
            }
        }
        , cancelCommand: function (cid) {
            var QP = new Core.Database.QueryParameters();
            QP.Add("CommandId", "INT", cid); 

            app.CallProcedure(app.DatabaseNames.System + ".ACCADMIN.CancelCommand", QP, {
                onSuccess: function (data) {
                },
                Secured: true,
            }, app.ConnectionStrings.app);
        }
        , clearCommand: function (e) {
            if (e) e.preventDefault(); 
            this.model.set("commandText", "");
            this.$el.find(".command-text").focus(); 
        }
        , clearDotCommand: function (e) {
            if (e) e.preventDefault();
            this.model.set("dotCommandText", "");
            this.$el.find(".dot-command-text").focus();
        }
        , 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;
            }
        }
        , refresh: function () {
            try {
                this.model.get("agents").fetch();
                this.model.get("dots").fetch();
            } catch (Error) { }
        }
        , refreshCommands: function () {
            var that = this;

            this.options.commandsTableAR = true; 
            if (this.options.commandsTableTOUT) {
                clearTimeout(this.options.commandsTableTOUT);
                this.options.commandsTableTOUT = null; 
            }
            
            this.model.get("commandTableRows").fetch({
                callback: function (e) {
                    if (that.options.commandsTableAR)
                        that.options.commandsTableTOUT = setTimeout(_.bind(that.refreshCommands, that), 1000); 
                }, 
            }); 
        }
        , stopRefreshCommmands: function () {
            this.options.commandsTableAR = false;
            if (this.options.commandsTableTOUT) {
                clearTimeout(this.options.commandsTableTOUT);
                this.options.commandsTableTOUT = null;
            }
        }
        , 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
        }
        , close: function () {
            this.stopRefreshCommmands();

            this.options.state = app.view_states.closed;

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

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

            this.refreshCommands();

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

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

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

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

        , reRender: function () {
        }
    });

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

});
