// tslint:disable-next-line:max-file-line-count
import { Component, EventEmitter, ViewEncapsulation } from '@angular/core';
import { RuleModel, RuleService, ConditionGroupModel, ConditionModel, ActionModel, RuleEngineState } from './services/Rule';
import { ServerSideTypeModel } from './services/ServerSideFieldModel';
import { ConditionService } from './services/Condition';
import { ActionService } from './services/Action';
import { ConditionGroupService } from './services/ConditionGroup';
import { I18nService } from './services/system/locale/I18n';
import { Observable } from 'rxjs/Observable';
import { BundleService } from './services/bundle-service';
import { ActivatedRoute } from '@angular/router';
import { HttpCode } from 'dotcms-js/dotcms-js';
import { LoggerService } from 'dotcms-js/dotcms-js';
import './semantic/assets/semantic.js';
// tslint:disable-next-line:no-unused-variable
var I8N_BASE = 'api.sites.ruleengine';
/**
 *
 */
var RuleEngineContainer = (function () {
    function RuleEngineContainer(_ruleService, _ruleActionService, _conditionGroupService, _conditionService, _resources, bundleService, route, loggerService) {
        var _this = this;
        this._ruleService = _ruleService;
        this._ruleActionService = _ruleActionService;
        this._conditionGroupService = _conditionGroupService;
        this._conditionService = _conditionService;
        this._resources = _resources;
        this.bundleService = bundleService;
        this.route = route;
        this.loggerService = loggerService;
        this.state = new RuleEngineState();
        this.environments = [];
        this.rules$ = new EventEmitter();
        this.ruleActions$ = new EventEmitter();
        this.conditionGroups$ = new EventEmitter();
        this.rules$.subscribe(function (rules) {
            _this.rules = rules;
        });
        this.bundleService
            .loadPublishEnvironments()
            .subscribe(function (environments) { return (_this.environments = environments); });
        this.initRules();
        this._ruleService._errors$.subscribe(function (res) {
            _this.state.globalError = res.message;
            _this.state.loading = false;
            _this.state.showRules = false;
        });
    }
    RuleEngineContainer.prototype.alphaSort = function (key) {
        return function (a, b) {
            var x;
            if (a[key] > b[key]) {
                x = 1;
            }
            else if (a[key] < b[key]) {
                x = -1;
            }
            else {
                x = 0;
            }
            return x;
        };
    };
    /**
   *
   * @param event
   */
    RuleEngineContainer.prototype.onCreateRule = function (event) {
        this.loggerService.info('RuleEngineContainer', 'onCreateRule', event);
        var priority = this.rules.length ? this.rules[0].priority + 1 : 1;
        var rule = new RuleModel({ priority: priority });
        var group = new ConditionGroupModel({ operator: 'AND', priority: 1 });
        group._conditions.push(new ConditionModel({ _type: new ServerSideTypeModel() }));
        rule._conditionGroups.push(group);
        var action = new ActionModel(null, new ServerSideTypeModel());
        action._owningRule = rule;
        rule._ruleActions.push(action);
        rule._saved = false;
        rule._expanded = true;
        this.rules$.emit([rule].concat(this.rules));
    };
    RuleEngineContainer.prototype.onDeleteRule = function (event) {
        var _this = this;
        var rule = event.payload.rule;
        rule._deleting = true;
        this.state.deleting = true;
        if (rule.isPersisted()) {
            this._ruleService.deleteRule(rule.key).subscribe(function (result) {
                _this.state.deleting = false;
            });
        }
        var rules = this.rules.filter(function (arrayRule) { return arrayRule.key !== rule.key; });
        this.rules$.emit(rules);
    };
    RuleEngineContainer.prototype.onUpdateEnabledState = function (event) {
        event.payload.rule.enabled = event.payload.value;
        this.patchRule(event.payload.rule, false);
    };
    RuleEngineContainer.prototype.onUpdateRuleName = function (event) {
        event.payload.rule.name = event.payload.value;
        this.patchRule(event.payload.rule, false);
    };
    RuleEngineContainer.prototype.onUpdateFireOn = function (event) {
        this.loggerService.info('RuleEngineContainer', 'onUpdateFireOn', event);
        event.payload.rule.fireOn = event.payload.value;
        this.patchRule(event.payload.rule, false);
    };
    RuleEngineContainer.prototype.onUpdateExpandedState = function (event) {
        var _this = this;
        var rule = event.payload.rule;
        rule._expanded = event.payload.value;
        if (rule._expanded) {
            var obs2 = void 0;
            if (rule._conditionGroups.length === 0) {
                var obs = this._conditionGroupService.allAsArray(rule.key, Object.keys(rule.conditionGroups));
                obs2 = obs.flatMap(function (groups) { return Observable.from(groups); });
            }
            else {
                obs2 = Observable.from(rule._conditionGroups);
            }
            var obs3 = obs2.flatMap(function (group) {
                return _this._conditionService.listForGroup(group, _this._ruleService._conditionTypes);
            }, function (group, conditions) {
                if (conditions) {
                    conditions.forEach(function (condition) {
                        condition.type = _this._ruleService._conditionTypes[condition.conditionlet];
                    });
                }
                group._conditions = conditions;
                return group;
            });
            var obs4 = obs3.reduce(function (acc, group) {
                acc.push(group);
                return acc;
            }, []);
            obs4.subscribe(function (groups) {
                rule._conditionGroups = groups;
                if (rule._conditionGroups.length === 0) {
                    _this.loggerService.info('RuleEngineContainer', 'conditionGroups', 'Add stub group');
                    var group = new ConditionGroupModel({ operator: 'AND', priority: 1 });
                    group._conditions.push(new ConditionModel({
                        _type: new ServerSideTypeModel(),
                        operator: 'AND',
                        priority: 1
                    }));
                    rule._conditionGroups.push(group);
                }
                else {
                    rule._conditionGroups.sort(_this.prioritySortFn);
                    rule._conditionGroups.forEach(function (group) {
                        group._conditions.sort(_this.prioritySortFn);
                        if (group._conditions.length === 0) {
                            group._conditions.push(new ConditionModel({
                                _type: new ServerSideTypeModel(),
                                operator: 'AND',
                                priority: 1
                            }));
                        }
                    });
                }
            }, function (e) {
                _this.loggerService.error('RuleEngineContainer', e);
            });
            if (rule._ruleActions.length === 0) {
                this._ruleActionService
                    .allAsArray(rule.key, Object.keys(rule.ruleActions), this._ruleService._ruleActionTypes)
                    .subscribe(function (actions) {
                    rule._ruleActions = actions;
                    if (rule._ruleActions.length === 0) {
                        var action = new ActionModel(null, new ServerSideTypeModel(), 1);
                        rule._ruleActions.push(action);
                        rule._ruleActions.sort(_this.prioritySortFn);
                    }
                    else {
                        rule._ruleActions.sort(_this.prioritySortFn);
                    }
                });
            }
        }
    };
    RuleEngineContainer.prototype.onCreateRuleAction = function (event) {
        this.loggerService.info('RuleEngineContainer', 'onCreateRuleAction', event);
        var rule = event.payload.rule;
        var priority = rule._ruleActions.length
            ? rule._ruleActions[rule._ruleActions.length - 1].priority + 1
            : 1;
        var entity = new ActionModel(null, new ServerSideTypeModel(), priority);
        this.patchRule(rule, true);
        rule._ruleActions.push(entity);
        rule._saved = false;
    };
    RuleEngineContainer.prototype.onDeleteRuleAction = function (event) {
        this.loggerService.info('RuleEngineContainer', 'onDeleteRuleAction', event);
        var rule = event.payload.rule;
        var ruleAction = event.payload.ruleAction;
        if (ruleAction.isPersisted()) {
            this._ruleActionService.remove(rule.key, ruleAction).subscribe(function (result) {
                rule._ruleActions = rule._ruleActions.filter(function (aryAction) {
                    return aryAction.key !== ruleAction.key;
                });
                if (rule._ruleActions.length === 0) {
                    rule._ruleActions.push(new ActionModel(null, new ServerSideTypeModel(), 1));
                }
            });
        }
    };
    RuleEngineContainer.prototype.onUpdateRuleActionType = function (event) {
        this.loggerService.info('RuleEngineContainer', 'onUpdateRuleActionType');
        try {
            var ruleAction = event.payload.ruleAction;
            var rule = event.payload.rule;
            var idx = event.payload.index;
            var type = this._ruleService._ruleActionTypes[event.payload.value];
            rule._ruleActions[idx] = new ActionModel(ruleAction.key, type, ruleAction.priority);
            this.patchAction(rule, ruleAction);
        }
        catch (e) {
            this.loggerService.error('RuleComponent', 'onActionTypeChange', e);
        }
    };
    RuleEngineContainer.prototype.onUpdateRuleActionParameter = function (event) {
        this.loggerService.info('RuleEngineContainer', 'onUpdateRuleActionParameter');
        var ruleAction = event.payload.ruleAction;
        ruleAction.setParameter(event.payload.name, event.payload.value);
        this.patchAction(event.payload.rule, ruleAction);
    };
    RuleEngineContainer.prototype.onCreateConditionGroup = function (event) {
        this.loggerService.info('RuleEngineContainer', 'onCreateConditionGroup');
        var rule = event.payload.rule;
        var priority = rule._conditionGroups.length
            ? rule._conditionGroups[rule._conditionGroups.length - 1].priority + 1
            : 1;
        var group = new ConditionGroupModel({ operator: 'AND', priority: priority });
        group._conditions.push(new ConditionModel({ _type: new ServerSideTypeModel(), operator: 'AND', priority: 1 }));
        rule._conditionGroups.push(group);
        rule._conditionGroups.sort(this.prioritySortFn);
    };
    RuleEngineContainer.prototype.onUpdateConditionGroupOperator = function (event) {
        this.loggerService.info('RuleEngineContainer', 'onUpdateConditionGroupOperator');
        var group = event.payload.conditionGroup;
        group.operator = event.payload.value;
        if (group.key != null) {
            this.patchConditionGroup(event.payload.rule, group);
            this.patchRule(event.payload.rule);
        }
    };
    RuleEngineContainer.prototype.onDeleteConditionGroup = function (event) {
        var rule = event.payload.rule;
        var group = event.payload.conditionGroup;
        this._conditionGroupService.remove(rule.key, group).subscribe();
        rule._conditionGroups = rule._conditionGroups.filter(function (aryGroup) { return aryGroup.key !== group.key; });
    };
    RuleEngineContainer.prototype.onCreateCondition = function (event) {
        var rule = event.payload.rule;
        this.ruleUpdating(rule, true);
        try {
            var group = event.payload.conditionGroup;
            var priority = group._conditions.length
                ? group._conditions[group._conditions.length - 1].priority + 1
                : 1;
            var entity = new ConditionModel({
                _type: new ServerSideTypeModel(),
                operator: 'AND',
                priority: priority
            });
            group._conditions.push(entity);
            this.ruleUpdated(rule);
        }
        catch (e) {
            this.loggerService.error('RuleEngineContainer', 'onCreateCondition', e);
            this.ruleUpdated(rule, [{ unhandledError: e }]);
        }
    };
    RuleEngineContainer.prototype.onUpdateConditionType = function (event) {
        this.loggerService.info('RuleEngineContainer', 'onUpdateConditionType');
        try {
            var condition = event.payload.condition;
            var group = event.payload.conditionGroup;
            var rule = event.payload.rule;
            var idx = event.payload.index;
            var type = this._ruleService._conditionTypes[event.payload.value];
            // replace the condition rather than mutate it to force event for 'onPush' NG2 components.
            condition = new ConditionModel({
                _type: type,
                id: condition.key,
                operator: condition.operator,
                priority: condition.priority
            });
            group._conditions[idx] = condition;
            this.patchCondition(rule, group, condition);
        }
        catch (e) {
            this.loggerService.error('RuleComponent', 'onActionTypeChange', e);
        }
    };
    RuleEngineContainer.prototype.onUpdateConditionParameter = function (event) {
        this.loggerService.info('RuleEngineContainer', 'onUpdateConditionParameter');
        var condition = event.payload.condition;
        condition.setParameter(event.payload.name, event.payload.value);
        this.patchCondition(event.payload.rule, event.payload.conditionGroup, condition);
    };
    RuleEngineContainer.prototype.onUpdateConditionOperator = function (event) {
        this.loggerService.info('RuleEngineContainer', 'onUpdateConditionOperator');
        var condition = event.payload.condition;
        condition.operator = event.payload.value;
        this.patchCondition(event.payload.rule, event.payload.conditionGroup, condition);
    };
    RuleEngineContainer.prototype.onDeleteCondition = function (event) {
        var _this = this;
        this.loggerService.info('RuleEngineContainer', 'onDeleteCondition', event);
        var rule = event.payload.rule;
        var group = event.payload.conditionGroup;
        var condition = event.payload.condition;
        if (condition.isPersisted()) {
            this._conditionService.remove(condition).subscribe(function (result) {
                group._conditions = group._conditions.filter(function (aryCondition) {
                    return aryCondition.key !== condition.key;
                });
                if (group._conditions.length === 0) {
                    _this.loggerService.info('RuleEngineContainer', 'condition', 'Remove Condition and remove Groups is empty');
                    _this._conditionGroupService.remove(rule.key, group).subscribe();
                    rule._conditionGroups = rule._conditionGroups.filter(function (aryGroup) { return aryGroup.key !== group.key; });
                }
                if (rule._conditionGroups.length === 0) {
                    _this.loggerService.info('RuleEngineContainer', 'conditionGroups', 'Add stub group if Groups are empty');
                    var group_1 = new ConditionGroupModel({ operator: 'AND', priority: 1 });
                    group_1._conditions.push(new ConditionModel({
                        _type: new ServerSideTypeModel(),
                        operator: 'AND',
                        priority: 1
                    }));
                    rule._conditionGroups.push(group_1);
                }
            });
        }
    };
    RuleEngineContainer.prototype.ruleUpdating = function (rule, disable) {
        if (disable === void 0) { disable = true; }
        if (disable && rule.enabled && rule.key) {
            this.loggerService.info('RuleEngineContainer', 'ruleUpdating', 'disabling rule due for edit.');
            this.patchRule(rule, true);
        }
        rule._saved = false;
        rule._saving = true;
        rule._errors = null;
    };
    RuleEngineContainer.prototype.ruleUpdated = function (rule, errors) {
        rule._saving = false;
        if (!errors) {
            rule._saved = true;
        }
        else {
            this.loggerService.error(errors);
            rule._errors = errors;
        }
    };
    RuleEngineContainer.prototype.patchConditionGroup = function (rule, group, disable) {
        if (disable === void 0) { disable = true; }
        this.ruleUpdating(rule, false);
        if (disable && rule.enabled) {
            rule.enabled = false;
        }
        this._conditionGroupService.updateConditionGroup(rule.key, group).subscribe(function (result) { });
    };
    RuleEngineContainer.prototype.patchRule = function (rule, disable) {
        var _this = this;
        if (disable === void 0) { disable = true; }
        this.ruleUpdating(rule, false);
        if (disable && rule.enabled) {
            rule.enabled = false;
        }
        if (rule.isValid()) {
            if (rule.isPersisted()) {
                this._ruleService.updateRule(rule.key, rule).subscribe(function () {
                    _this.ruleUpdated(rule);
                }, function (e) {
                    var ruleError = _this._handle403Error(e) ? null : { invalid: e.message };
                    _this.ruleUpdated(rule, ruleError);
                });
            }
            else {
                this._ruleService.createRule(rule).subscribe(function () {
                    _this.ruleUpdated(rule);
                }, function (e) {
                    var ruleError = _this._handle403Error(e) ? null : { invalid: e.message };
                    _this.ruleUpdated(rule, ruleError);
                });
            }
        }
        else {
            this.ruleUpdated(rule, {
                invalid: 'Cannot save, rule is not valid.'
            });
        }
    };
    RuleEngineContainer.prototype.patchAction = function (rule, ruleAction) {
        var _this = this;
        this.ruleUpdating(rule);
        if (ruleAction.isValid()) {
            if (!ruleAction.isPersisted()) {
                this._ruleActionService.createRuleAction(rule.key, ruleAction).subscribe(function (result) {
                    _this.ruleUpdated(rule);
                }, function (e) {
                    var ruleError = _this._handle403Error(e) ? null : { invalid: e.message };
                    _this.ruleUpdated(rule, ruleError);
                });
            }
            else {
                this._ruleActionService.updateRuleAction(rule.key, ruleAction).subscribe(function (result) {
                    _this.ruleUpdated(rule);
                }, function (e) {
                    var ruleError = _this._handle403Error(e) ? null : { invalid: e.message };
                    _this.ruleUpdated(rule, ruleError);
                });
            }
        }
        else {
            this.ruleUpdated(rule, {
                invalid: 'Cannot save, action is not valid.'
            });
        }
    };
    RuleEngineContainer.prototype.patchCondition = function (rule, group, condition) {
        var _this = this;
        this.ruleUpdating(rule);
        try {
            if (condition.isValid()) {
                if (condition.isPersisted()) {
                    this._conditionService.save(group.key, condition).subscribe(function (result) {
                        _this.ruleUpdated(rule);
                    }, function (e) {
                        var ruleError = _this._handle403Error(e)
                            ? null
                            : { invalid: e.message };
                        _this.ruleUpdated(rule, ruleError);
                    });
                }
                else {
                    if (!group.isPersisted()) {
                        this._conditionGroupService
                            .createConditionGroup(rule.key, group)
                            .subscribe(function (foo) {
                            _this._conditionService.add(group.key, condition).subscribe(function () {
                                group.conditions[condition.key] = true;
                                _this.ruleUpdated(rule);
                            }, function (e) {
                                var ruleError = _this._handle403Error(e)
                                    ? null
                                    : { invalid: e.message };
                                _this.ruleUpdated(rule, ruleError);
                            });
                        });
                    }
                    else {
                        this._conditionService.add(group.key, condition).subscribe(function () {
                            group.conditions[condition.key] = true;
                            _this.ruleUpdated(rule);
                        }, function (e) {
                            var ruleError = _this._handle403Error(e)
                                ? null
                                : { invalid: e.message };
                            _this.ruleUpdated(rule, ruleError);
                        });
                    }
                }
            }
            else {
                this.loggerService.info('RuleEngineContainer', 'patchCondition', 'Not valid');
                rule._saving = false;
                rule._errors = { invalid: 'Condition not valid.' };
            }
        }
        catch (e) {
            this.loggerService.error(e);
            this.ruleUpdated(rule, { invalid: e.message });
        }
    };
    RuleEngineContainer.prototype.prioritySortFn = function (a, b) {
        return a.priority - b.priority;
    };
    // tslint:disable-next-line:no-unused-variable
    RuleEngineContainer.prototype.preCacheCommonResources = function (resources) {
        resources.get('api.sites.ruleengine').subscribe(function (rsrc) { });
        resources.get('api.ruleengine.system').subscribe(function (rsrc) { });
        resources.get('api.system.ruleengine').subscribe(function (rsrc) { });
    };
    RuleEngineContainer.prototype.initRules = function () {
        var _this = this;
        this.state.loading = true;
        var siteId = '';
        this.route.queryParams.subscribe(function (params) {
            siteId = params['realmId'];
        });
        this._ruleService.requestRules(siteId);
        this._ruleService.loadRules().subscribe(function (rules) {
            _this.loadRules(rules);
        });
    };
    RuleEngineContainer.prototype.loadRules = function (rules) {
        rules.sort(function (a, b) {
            return b.priority - a.priority;
        });
        this.rules$.emit(rules);
        this.state.loading = false;
    };
    RuleEngineContainer.prototype._handle403Error = function (e) {
        var handled = false;
        try {
            if (e && e.response.status === HttpCode.FORBIDDEN) {
                var errorJson = e.response.json();
                if (errorJson && errorJson.error) {
                    this.state.globalError = errorJson.error.replace('dotcms.api.error.forbidden: ', '');
                    handled = true;
                }
            }
        }
        catch (e) {
            this.loggerService.error('Error while processing invalid response: ', e);
        }
        return handled;
    };
    return RuleEngineContainer;
}());
export { RuleEngineContainer };
RuleEngineContainer.decorators = [
    { type: Component, args: [{
                encapsulation: ViewEncapsulation.None,
                selector: 'cw-rule-engine-container',
                styles: [
                    require('./styles/rule-engine.scss'),
                    require('./styles/angular-material.layouts.scss'),
                    require('./semantic/assets/semantic.css')
                ],
                // styleUrls: [
                //     './styles/rule-engine.scss',
                //     './styles/angular-material.layouts.scss',
                //     './semantic/assets/semantic.css'
                // ],
                template: "\n    <cw-rule-engine\n      [environmentStores]=\"environments\"\n      [rules]=\"rules\"\n      [ruleActionTypes]=\"_ruleService._ruleActionTypes\"\n      [conditionTypes]=\"_ruleService._conditionTypes\"\n      [loading]=\"state.loading\"\n      [showRules]=\"state.showRules\"\n      [globalError]=\"state.globalError\"\n      (createRule)=\"onCreateRule($event)\"\n      (deleteRule)=\"onDeleteRule($event)\"\n      (updateName)=\"onUpdateRuleName($event)\"\n      (updateFireOn)=\"onUpdateFireOn($event)\"\n      (updateEnabledState)=\"onUpdateEnabledState($event)\"\n      (updateExpandedState)=\"onUpdateExpandedState($event)\"\n\n      (createRuleAction)=\"onCreateRuleAction($event)\"\n      (updateRuleActionType)=\"onUpdateRuleActionType($event)\"\n      (updateRuleActionParameter)=\"onUpdateRuleActionParameter($event)\"\n      (deleteRuleAction)=\"onDeleteRuleAction($event)\"\n\n      (createConditionGroup)=\"onCreateConditionGroup($event)\"\n      (updateConditionGroupOperator)=\"onUpdateConditionGroupOperator($event)\"\n      (createCondition)=\"onCreateCondition($event)\"\n      (updateConditionType)=\"onUpdateConditionType($event)\"\n      (updateConditionParameter)=\"onUpdateConditionParameter($event)\"\n      (updateConditionOperator)=\"onUpdateConditionOperator($event)\"\n      (deleteCondition)=\"onDeleteCondition($event)\"\n    ></cw-rule-engine>\n"
            },] },
];
/** @nocollapse */
RuleEngineContainer.ctorParameters = function () { return [
    { type: RuleService, },
    { type: ActionService, },
    { type: ConditionGroupService, },
    { type: ConditionService, },
    { type: I18nService, },
    { type: BundleService, },
    { type: ActivatedRoute, },
    { type: LoggerService, },
]; };
//# sourceMappingURL=rule-engine.container.js.map