'use strict';

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.Rule = undefined;

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _criteria = require('./criteria.js');

var _behavior = require('./behavior.js');

function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var Rule = exports.Rule = function () {
    function Rule(name, criteria, criteriaMustSatisfy, behaviors, children, skipBehaviors, valueMap, depth) {
        _classCallCheck(this, Rule);

        this.name = name;
        this.criteria = criteria;
        this.criteriaMustSatisfy = criteriaMustSatisfy;
        this.behaviors = behaviors;
        this.children = children;
        this.skipBehaviors = skipBehaviors;
        this.valueMap = valueMap;
        this.depth = depth;
    }

    _createClass(Rule, [{
        key: 'process',
        value: function process() {

            var result = '\n' + this.pad(this.depth) + '-- ' + this.name + ' rule ####';
            var criteriaNames = this.criteriaNames(this.criteria) ? this.criteriaNames(this.criteria) : 'none';
            result += '\n' + this.pad(this.depth) + '-- criteria: ' + criteriaNames;

            if (this.criteriaNamesNotRegistered(this.criteria) !== '') {
                console.error('Criteria not registered: ' + this.criteriaNamesNotRegistered(this.criteria));
            }

            if (this.anyCriteriaForRuleRegistered(this.criteria)) {
                result += '\n' + this.pad(this.depth) + 'if ' + this.processCriteria(this.criteria, this.valueMap) + ' then';
            }

            if (this.behaviors && typeof this.behaviors !== 'undefined' && this.behaviors.length > 0) {
                result += this.pad(this.depth + 1) + this.processBehaviors(this.behaviors, this.valueMap, this.skipBehaviors) + '\n';
            }

            var that = this;
            this.children.forEach(function (childRule) {
                var rule = new Rule(childRule.name, childRule.criteria, childRule.criteriaMustSatisfy, childRule.behaviors, childRule.children, that.skipBehaviors, that.valueMap, that.depth + 1);
                result += rule.process();
            });

            if (this.anyCriteriaForRuleRegistered(this.criteria)) {
                result += this.pad(this.depth) + 'end\n';
            }

            return result;
        }
    }, {
        key: 'anyCriteriaForRuleRegistered',
        value: function anyCriteriaForRuleRegistered(criteria) {
            if (!criteria) return false;
            var anyCriteriaRegistered = false;
            criteria.forEach(function (criteria) {
                if (_criteria.Criteria.isRegistered(criteria.name)) {
                    anyCriteriaRegistered = true;
                }
            });
            return anyCriteriaRegistered;
        }
    }, {
        key: 'criteriaNames',
        value: function criteriaNames(criteria) {
            if (!criteria) return '';
            var criteriaNameArray = [];
            criteria.forEach(function (criteria) {
                criteriaNameArray.push(criteria.name);
            });
            return '(' + criteriaNameArray.join(this.criteriaJoiner()) + ')';
        }
    }, {
        key: 'criteriaNamesNotRegistered',
        value: function criteriaNamesNotRegistered(criteria) {
            if (!criteria) return '';
            var criteriaNameArray = [];
            criteria.forEach(function (criteria) {
                if (!_criteria.Criteria.isRegistered(criteria.name)) {
                    criteriaNameArray.push(criteria.name);
                }
            });
            return criteriaNameArray.join(', ');
        }
    }, {
        key: 'processCriteria',
        value: function processCriteria(criteria, valueMap) {
            if (!criteria) return null;
            var criteriaArray = [];
            criteria.forEach(function (criteria) {
                if (_criteria.Criteria.isRegistered(criteria.name)) {
                    var item = new _criteria.Criteria(criteria.name, criteria.options, valueMap);
                    criteriaArray.push(item.process());
                }
            });
            return '(' + criteriaArray.join(this.criteriaJoiner()) + ')';
        }
    }, {
        key: 'processBehaviors',
        value: function processBehaviors(behaviors, valueMap, skipBehaviors) {
            if (!behaviors) return null;
            var behaviorArray = [];
            behaviors.forEach(function (behavior) {
                var item = new _behavior.Behavior(behavior.name, behavior.options, valueMap);

                if (skipBehaviors.includes(behavior.name)) {
                    behaviorArray.push('-- ' + behavior.name + ' behavior (skipped)');
                } else {
                    behaviorArray.push('-- ' + behavior.name + ' behavior');
                    var behaviourResult = item.process();
                    if (behaviourResult) {
                        if (Array.isArray(behaviourResult)) {
                            behaviorArray = [].concat(_toConsumableArray(behaviorArray), _toConsumableArray(behaviourResult));
                        } else {
                            behaviorArray.push(behaviourResult);
                        }
                    }
                }
            });
            return '\n' + this.pad(this.depth + 1) + behaviorArray.join('\n' + this.pad(this.depth + 1));
        }
    }, {
        key: 'criteriaJoiner',
        value: function criteriaJoiner() {
            var joiner = ') and (';

            switch (this.criteriaMustSatisfy) {
                case 'all':
                    joiner = ') and (';
                    break;
                case 'any':
                    joiner = ') or (';
                    break;
            }
            return joiner;
        }
    }, {
        key: 'pad',
        value: function pad(count) {
            if (!count || count < 0) {
                count = 0;
            }
            return new Array(count + 1).join('\t');
        }
    }]);

    return Rule;
}();