define(['./group.js'], function (Group) {

    /**
     * Collection of groups
     * @class
     * @constructor
     * @property {Object} groups - an array of group instances
     */
    var Groups = function () {
        this.collection = new Groups.Collection();
        this.view = new Groups.View();
        this.collection.setView(this.view);
        this.view.setCollection(this.collection);
    };

    Groups.Collection = function () {
        this.view = null;
        /**
         * Array of Group objects
         * @private
         * @type {Array}
         */
        this.groups = [];
    };

    Groups.Collection.prototype = (function () {
        var setView = function (view) {
            this.view = view;
        };

        /**
         * Add models to the collection
         * @private
         * @memberOf Groups
         * @param {Object} data - JSON data or array of Group objects
         */
        var setData = function (data) {
            var self = this;
            _.each(data, function (group) {
                if (group instanceof Group) {
                    self.groups.push(group);
                } else {
                    var instance = new Group();
                    instance.model.setData(group);
                    self.groups.push(instance);
                }
            });
        };

        /**
         * Get models from the collection
         * @private
         * @memberOf Groups
         * @returns {Array}
         */
        var getData = function () {
            if (_.isArray(this.groups)) {
                return this.groups;
            } else {
                return [];
            }
        };

        /**
         * Filter Groups collection by name, label or sym_name
         * @private
         * @memberOf Groups
         */
        var filter = function () {
            var needle = $('#filterGroups').val().toLocaleLowerCase();
            if (_.isString(needle) && needle !== '') {
                var groups = Instance.Groups.collection.groups;
                var result = _.filter(groups, function (group) {
                    var match = false;
                    if (_.isString(group.model.name) && group.model.name !== '') {
                        var groupName = group.model.name.toLocaleLowerCase();
                        if (groupName.indexOf(needle) !== -1) {
                            match = true;
                        }
                        if (_.isArray(group.model.fields)) {
                            _.each(group.model.fields, function (field) {
                                if (_.isString(field.fieldSymName)) {
                                    var symName = field.model.fieldSymName.toLocaleLowerCase();
                                    if (symName.indexOf(needle) !== -1) {
                                        match = true;
                                    }
                                }
                                if (_.isString(field.model.label)) {
                                    var label = field.model.label.toLocaleLowerCase();
                                    if (label.indexOf(needle) !== -1) {
                                        match = true;
                                    }
                                }
                            });
                        }
                    }
                    return match;
                });
                return result;
            }
        };

        /**
         *
         * @private
         * @memberOf Groups
         * @param {Number} groupId
         * @returns {Object} Group
         */
        var getByGroupId = function (groupId) {
            var group = _.find(this.groups, function (group) {
                return parseInt(group.model.id, 10) === parseInt(groupId, 10);
            });
            return group;
        };

        /**
         *
         * @private
         * @memberOf Groups
         * @param {Number} groupId
         * @returns {Number} index
         */
        var getIndexByGroupId = function (groupId) {
            var index = _.findIndex(this.groups, function (group) {
                return parseInt(group.model.id, 10) === parseInt(groupId, 10);
            });
            return index;
        };

        return {
            setView: setView,

            /**
             * Groups initialisation
             * @public
             * @memberOf Groups
             */
            setData: setData,

            /**
             * Get an array of Group objects
             * @public
             * @memberOf Groups
             */
            groups: getData,

            /**
             * Filter the list of groups
             * @public
             * @memberOf Groups
             */
            filter: filter,

            /**
             * Fetch a group from the Groups collection by id
             * @public
             * @memberOf Groups
             * @param {Number} groupId    - group id
             * @returns {Object}
             */
            getByGroupId: getByGroupId,

            /**
             * Fetch the index from the Groups collection
             * @public
             * @memberOf Groups
             * @param {Number} groupId    - group id
             * @returns {Number}
             */
            getIndexByGroupId: getIndexByGroupId
        };
    })();

    Groups.View = function () {
        'use strict';
        this.collection = null;
        this.el = null;
        this.init();
    };

    Groups.View.prototype = (function () {
        'use strict';
        var setCollection = function (collection) {
            this.collection = collection;
        };

        var init = function () {
            setElement.call(this);
        };

        /**
         * Render groups
         * @private
         * @memberOf Groups
         * @param {Object} [data]
         */
        var render = function (data) {
            this.el.empty();
            if (_.isUndefined(data)) {
                var needle = $('#filterGroups').val().toLocaleLowerCase();
                if (_.isString(needle) && needle !== '' && $('#filterGroups').attr('placeholder') !== lmsg('infocapture.admin.field_rights.filter_input')) {
                    _.each(Instance.Groups.collection.filter(), function (group) {
                        group.view.render();
                    });
                } else {
                    _.each(this.collection.groups, function (group) {
                        group.view.render();
                    });
                }
            } else {
                _.each(data, function (group) {
                    group.view.render();
                });
            }
            $('#filter-form').submit(filter);
            $('#filterGroups').keyup(_.debounce(filter, 1000));
            $('#resetFilterGroups').on('click', clearFilter);
        };

        /**
         * Empty filter input and call render
         * @private
         * @memberOf Groups
         */
        var clearFilter = function () {
            $('#filterGroups').val('');
            Instance.Groups.view.render();
        };

        var filter = function (event) {
            if (typeof event !== 'undefined') {
                event.preventDefault();
            }
            Instance.Groups.view.render(Instance.Groups.collection.filter());
        };

        var setElement = function () {
            this.el = $('#group-list');
        };

        var getElement = function () {
            return this.el;
        };

        return {
            filter: filter,
            setCollection: setCollection,
            init: init,

            el: getElement,
            /**
             * Clear the filter value
             * @public
             * @memberOf Groups
             * @returns {Object}
             */
            clearFilter: clearFilter,

            /**
             * Render groups collection
             * @public
             * @memberOf Groups
             * @return {Object} Groups
             */
            render: render
        };
    })();

    return Groups;
});
