define([
  'app',
],
function (app) {

    var Main = {
        Models: {},
        Collections: {},
    };

    Main.Models.UserProperty = Backbone.Epoxy.Model.extend({
        defaults: {
            userId: null,
            userName: null,
            //userPropertyCode: null,
            //userPropertyData: null,
            //userPropertyName: null,
            //userPropertyType: null,
            code: null,
            defaultValue: null,
            name: null,
            value: null
        },

        parse: function (obj) {
            return {
                userId: obj.UserId,
                userName: obj.UserName,
                //userPropertyCode: obj.UserPropertyCode,
                code: obj.UserPropertyCode,
                defaultValue: obj.UserPropertyDefaultValue,
                name:  obj.Name, //obj.UserPropertyName,
                value: obj.Value,
            };
        },
    });

    Main.Collections.UserProperties = Backbone.Collection.extend({
        model: Main.Models.UserProperty,

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

        comparator: function (a, b) {
            //Check user name
            var valA = a.get('userName'),
                valB = b.get('userName');

            if (valA < valB)
                return -1;
            else if (valA > valB)
                return 1;

            //Check name
            valA = a.get('name');
            valB = b.get('name');

            if (valA < valB)
                return -1;
            else if (valA > valB)
                return 1;


            //Equals
            return 0;
        },

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

            if (opt.reset) {
                this.resetPagination(true);

                this.fixedParameters = [
                    { Name: '@userId', Type: 'INT', Value: opt.params.userId, },
                    //{ Name: '@userPropertyCode', Type: 'VARCHAR', Value: opt.params.userPropertyCode, },
                ];
            }

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

            //if (opt.refresh) {
            //    qp.Add('@fromRow', 'INT', 0);
            //    qp.Add('@rowsToFetch', 'INT', this.currentPage * this.pageSize);
            //}
            //else if (opt.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 + '.CAT.GetUserProperties',
                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 = ((opt.refresh) || ((opt.reset))) ? 'set' : 'add';

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

                                if (!opt.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 (error) { console.error((error.stack) ? error.stack : new Error(error).stack); }
                    },
                    Async: opt.async,
                    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);
            }
        },
        update: function (options) {
            var that = this,
                qp = new Core.Database.QueryParameters(),
                opt = _.extend({
                    params: {},
                    async: true,
                }, options);


            qp.Add('userId', 'INT', opt.params.userId);

            qp.Add(
                'properties',
                'XML',
                app.jsonArrayToXml(
                    this.toJSON(),
                    [
                        'code',
                        'value',
                    ]
                )
            );

            Core.Json.CallProcedure(
                app.DatabaseNames.MES + '.CAT.UpdateUserProperties',
                qp,
                {
                    onSuccess: function (resp) {
                        try {
                            if ((resp) && (!resp.Message)) {

                                if (opt.success)
                                    opt.success(resp);
                            }
                            else {
                                var errorMsg = ((resp) && (resp.Message))
                                                            ? resp.Message
                                                            : 'SERVER_RESPONSE_NOT_VALID';
                                console.error(errorMsg);

                                if (opt.error)
                                    opt.error(errorMsg);
                            }
                        }
                        catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                    },
                    onError: function (errorMsg) {
                        try {
                            console.error(errorMsg);

                            if (opt.error)
                                opt.error(errorMsg);
                        }
                        catch (e) { console.error((e.stack) ? e.stack : new Error(e).stack); }
                    },
                    Async: opt.async,
                    Secured: true,
                },
                app.ConnectionStrings.app
            );
        },
    });

    Main.Collections.CurrentUserProperties = new Main.Collections.UserProperties();
    Main.Collections.CurrentUserProperties.fetch({
        reset: true,
        params: {
            userId: -1,
        },
        async: false,
    });

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

});
