define(['./rule.js'], function (Rule) {

    /**
     * Rules class
     * @class Rules
     * @constructor
     * @property {Array} - array of Rule objects
     */
    var Rules = function (rules, fieldSymName) {
        this.collection = new Rules.Collection(rules, fieldSymName);

        this.view = new Rules.View();

        this.collection.setView(this.view);
        this.view.setCollection(this.collection);
    };

    Rules.Collection = function (rules, fieldSymName) {
        /**
         * @private
         * @type {Array}
         * @memberOf Rules
         */
        this.rules = [];

        /**
         * @private
         * @memberOf Rules
         */
        this.view = null;

        this.setData(rules, fieldSymName);
    };

    Rules.Collection.prototype = (function () {

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

        /**
         * @private
         * @memberOf Rules
         */
        var setData = function (data, fieldSymName) {
            var self = this;
            _.each(data, function (rule) {
                rule.fieldSymName = fieldSymName;
                var instance = new Rule(rule);
                self.rules.push(instance);
            });
        };

        /**
         *
         * @private
         * @memberOf Rules.Collection
         * @returns {Array}
         */
        var getData = function () {
            if (_.isArray(this.rules)) {
                return this.rules;
            } else {
                return [];
            }
        };

        /**
         * Fetch a field from the Fields collection by id
         * @private
         * @memberOf ICDynamicFieldChanges.Fields.Collection
         * @param {String} symName - field symbolic name
         * @returns {Object}
         */
        var getByRuleId = function (ruleId) {
            var rule = _.find(this.rules, function (rule) {
                //console.log(rule);
                //console.log(rule.model.id + ' === ' + ruleId);
                return rule.model.id === ruleId;
            });
            return rule;
        };

        /**
         * Fetch the index from the Fields collection
         * @private
         * @memberOf ICDynamicFieldChanges.Fields.Collection
         * @param {String} symName - field symbolic name
         * @returns {number}
         */
        var getIndexByRuleId = function (ruleId) {
            var index = _.findIndex(this.rules, function (rule) {
                return rule.model.id === ruleId;
            });
            return parseInt(index, 10);
        };

        return {
            setView: setView,
            /**
             * @public
             * @memberOf Rules.Collection
             */
            rules: getData,

            /**
             * @public
             * @memberOf Rules.Collection
             */
            setData: setData,

            getByRuleId: getByRuleId,

            getIndexByRuleId: getIndexByRuleId
        };
    })();

    Rules.View = function () {
        this.collection = null;
        /**
         * @private
         * @type {Object}
         * @memberOf Rules.View
         */
        this.el = null;
    };
    Rules.View.prototype = (function () {

        var setCollection = function (collection) {
            this.collection = collection;
        };

        /**
         * @private
         * @memberOf Rules.View
         */
        var render = function () {
            var self = this;
            _.each(this.collection.rules, function (rule) {
                rule.view.render(self.el);
            });
        };

        /**
         * @private
         * @memberOf Rules.View
         */
        var setElement = function (el) {
            this.el = el;
        };

        /**
         * @private
         * @memberOf Rules.View
         */
        var getElement = function () {
            return this.el;
        };
        return {

            setCollection: setCollection,

            /**
             * @public
             * @memberOf Rules.View
             */
            render: render,

            /**
             * @public
             * @memberOf Rules.View
             */
            el: getElement,

            /**
             * @public
             * @memberOf Rules.View
             */
            setElement: setElement
        };
    })();

    return Rules;
});
