import { EventEmitter } from '@angular/core';
import { sortBy } from 'lodash';
import { ConditionType } from './condition-type';
import { BitConditionItemObserver } from './bit-condition-item-observer';
import { RelationConditionResult } from './relation-condition-result';
import { WordConditionItemObserver } from './word-condition-item-observer';
import { RelationType } from './relation-type';
export class ConditionItemsResultObserver {
    constructor(sourceConditionItems, variableCommunicator, variableStore) {
        this.sourceConditionItems = sourceConditionItems;
        this.variableCommunicator = variableCommunicator;
        this.variableStore = variableStore;
        this.conditionResultChanged = new EventEmitter();
        this.conditionResults = new Map();
    }
    requestData(appId) {
        if (null == this.sourceConditionItems || !this.sourceConditionItems.length) {
            return;
        }
        const conditionItems = this.sourceConditionItems.sort(t => t.index);
        conditionItems.forEach(item => {
            switch (item.conditionType) {
                case ConditionType.Bit:
                    const bitItem = new BitConditionItemObserver(item.condition, this.variableCommunicator, this.variableStore);
                    bitItem.conditionEffectiveChanged.subscribe(itemResult => {
                        if (this.conditionResults.has(conditionItems.indexOf(item))) {
                            this.conditionResults.delete(conditionItems.indexOf(item));
                        }
                        this.conditionResults.set(conditionItems.indexOf(item), new RelationConditionResult(conditionItems.indexOf(item), item.relationType, itemResult));
                        this.emitConditionResult();
                    });
                    bitItem.requestData(appId);
                    break;
                case ConditionType.Word:
                    const wordItem = new WordConditionItemObserver(item.condition, this.variableCommunicator, this.variableStore);
                    wordItem.conditionEffectiveChanged.subscribe(itemResult => {
                        if (this.conditionResults.has(conditionItems.indexOf(item))) {
                            this.conditionResults.delete(conditionItems.indexOf(item));
                        }
                        this.conditionResults.set(conditionItems.indexOf(item), new RelationConditionResult(conditionItems.indexOf(item), item.relationType, itemResult));
                        this.emitConditionResult();
                    });
                    wordItem.requestData(appId);
                    break;
                default:
                    throw new Error(`Unknown ConditionType :${item.conditionType}`);
            }
        });
    }
    emitConditionResult() {
        let isControl = true;
        const elementStates = [];
        const formatConditionResults = [];
        this.conditionResults.forEach(t => {
            formatConditionResults.push({
                key: t.key,
                result: t
            });
            // eslint-disable-next-line eqeqeq
            if (t.relationType == RelationType.None) {
                isControl = t.result.value;
                elementStates.push(t.result.state);
            }
        });
        const formatResults = sortBy(formatConditionResults, data => {
            return data.key;
        });
        formatResults.forEach(item => {
            const relationCondition = item.result;
            // eslint-disable-next-line eqeqeq
            if (relationCondition.relationType == RelationType.Or) {
                isControl = isControl || relationCondition.result.value;
                elementStates.push(relationCondition.result.state);
                // eslint-disable-next-line eqeqeq
            }
            else if (relationCondition.relationType == RelationType.And) {
                isControl = isControl && relationCondition.result.value;
                elementStates.push(relationCondition.result.state);
            }
        });
        const conditionControlResult = {
            states: elementStates,
            value: isControl
        };
        this.conditionResultChanged.emit(conditionControlResult);
    }
}
