define(['./right.js'], function (Right) {

    /**
     * Collection of Right objects
     * @class
     * @constructor
     * @param {Object} rights - JSON object
     * @property {Object} rights - an array of Right objects
     * @property {Number} ruleId - rule the rights belong to
     * @propery {String} name - rule name the rights belong to
     * @property {Number} groupId - group id
     */
    var Rights = function () {
        'use strict';
        this.collection = new Rights.Collection();
        this.view = new Rights.View();
        this.collection.setView(this.view);
        this.view.setCollection(this.collection);
    };

    Rights.Collection = function () {
        'use strict';
        /**
         * @private
         */
        this.view = null;

        /**
         * Array of Right objects
         * @private
         * @type {Array}
         */
        this.rights = [];

        /**
         * Rule id the rights belong to
         * @private
         * @type {Number}
         */
        this.ruleId = null;

        /**
         * Rule name the rights belong to
         * @private
         * @type {String}
         */
        this.name = null;

        /**
         * Group id the rights belong to
         * @private
         * @type {Number}
         */
        this.groupId = null;

        this.position = null;
    };

    Rights.Collection.prototype = (function () {
        'use strict';
        var setView = function (view) {
            this.view = view;
        };

        /**
         * Add models to the collection
         * @private
         * @memberOf Rights
         * @param {Object} data - JSON data for all rules
         */
        var setData = function (data) {
            setRuleId.call(this, data.rule_id);
            setName.call(this, data.name);
            setGroupId.call(this, data.group_id);
            setRights.call(this, data.field_rights);
            setPosition.call(this, data.position);
        };

        var setRights = function (rights) {
            var self = this;
            _.each(rights, function (right) {
                if (right instanceof Right) {
                    self.rights.push(right);
                } else {
                    var instance = new Right('view');
                    instance.model.setData(right);
                    self.rights.push(instance);
                    instance = new Right('edit');
                    instance.model.setData(right);
                    self.rights.push(instance);
                }
            });
        };

        /**
         * Get all the rights
         * @private
         * @memberOf Rights
         * @returns {Array}
         */
        var getRights = function () {
            if (_.isArray(this.rights)) {
                return this.rights;
            } else {
                return [];
            }
        };

        var setRuleId = function (ruleId) {
            this.ruleId = parseInt(ruleId, 10);
        };

        /**
         * Get the rule id
         * @private
         * @memberOf Rights
         * @returns {Number}
         */
        var getRuleId = function () {
            if (_.isNumber(this.ruleId)) {
                return parseInt(this.ruleId, 10);
            } else {
                return NaN;
            }
        };

        var setName = function (name) {
            this.name = name;
        };

        /**
         * Get the rule name
         * @private
         * @memberOf Rights
         * @returns {String}
         */
        var getName = function () {
            if (_.isString(this.name)) {
                return this.name;
            } else {
                return '';
            }
        };

        var setGroupId = function (groupId) {
            this.groupId = parseInt(groupId, 10);
        };

        var getGroupId = function () {
            if (_.isNumber(this.groupId)) {
                return parseInt(this.groupId, 10);
            } else {
                return NaN;
            }
        };

        var setPosition = function (position) {
            this.position = parseInt(position, 10);
        };

        var getPosition = function () {
            if (_.isNumber(this.position)) {
                return parseInt(this.position, 10);
            } else {
                return NaN;
            }
        };

        /**
         * Fetch a group from the Rules collection by id
         * @public
         * @param {Number} ruleId    - grruleoup id
         * @returns {Object}
         */
        var getByBitmask = function (bitmask) {
            var right = _.find(this.rights, function (right) {
                return parseInt(right.model.bitmask, 10) === parseInt(bitmask, 10);
            });
            return right;
        };

        var getByBitmaskAndMode = function (bitmask, mode) {
            var right = _.find(this.rights, function (right) {
                return (parseInt(right.model.bitmask, 10) === parseInt(bitmask, 10) &&
                    right.model.mode === mode);
            });
            return right;
        };

        /**
         * Fetch the index from the Rules collection
         * @public
         * @returns {Number}
         * @param bitmask
         */
        var getIndexByBitmask = function (bitmask) {
            var index = _.findIndex(this.rights, function (right) {
                return parseInt(right.model.bitmask, 10) === parseInt(bitmask, 10);
            });
            return index;
        };

        /**
         * When a new rule is created this created the rights are populated
         * @private
         */
        var createDefaultRights = function () {
            var rights = [];
            _.each(Instance.Roles.collection.roles, function (role) {
                var right = {
                    bitmask: role.model.bitmask,
                    view: 0,
                    edit: 0
                };
                var instance = new Right('view');
                instance.model.setData(right);
                rights.push(instance);
                instance = new Right('edit');
                instance.model.setData(right);
                rights.push(instance);
            });
            return rights;
        };

        return {
            setView: setView,

            setRights: setRights,

            /**
             * Initialise object
             * @public
             * @memberOf Rights
             */
            setData: setData,

            /**
             * Get all array of rights
             * @public
             * @memberOf Rights
             * @returns {Array}
             */
            rights: getRights,

            /**
             * Get rule id
             * @public
             * @memberOf Rights
             * @returns {Number}
             */
            ruleId: getRuleId,

            /**
             * Get rule name
             * @public
             * @memberOf Rights
             * @returns {String}
             */
            name: getName,

            groupId: getGroupId,

            createDefaultRights: createDefaultRights,

            getByBitmask: getByBitmask,

            getByBitmaskAndMode: getByBitmaskAndMode,

            getIndexByBitmask: getIndexByBitmask
        };
    })();

    Rights.View = function (mode) {
        'use strict';
        this.collection = null;
        this.mode = mode;
    };

    Rights.View.prototype = (function () {
        'use strict';
        var setCollection = function (collection) {
            this.collection = collection;
        };
        /**
         * Set DOM element
         * @private
         * @param {Object} el - jQuery DOM element from Group.View
         */
        var setElement = function (el) {
            this.el = el.find('.rights-list');
        };

        /**
         * Get DOM element
         * @private
         * @returns {Object}
         */
        var getElement = function () {
            return this.el;
        };

        var render = function (el) {
            var self = this;
            setElement.call(this, el);
            this.el.append(_.template($('#rights-tmpl').html())(this.collection));
            _.each(this.collection.rights, function (right) {
                self.el.find('tr[data-rule-id=' + self.collection.ruleId + ']').find('td:last-child').before(right.view.render());
            });
        };

        return {
            setCollection: setCollection,

            render: render
        };
    })();

    return Rights;
});
