class ActionRule {
    constructor(field = false, action = false) {
        this.field = field;
        this.action = action;
    }

    isValid() {
        return this._createRule().check();
    }

    _createRule() {
        try {
            const rule = new Rule();
            const conditions = this.action.conditions;

            if (conditions) {
                for (const key in conditions) {
                    rule.addCondition(this._createCondition(conditions[key]));
                }
            } else {
                throw new Error('wrong conditions');
            }

            return rule;
        } catch (error) {
            console.error('_createRule', error);
        }
    }

    _createCondition(conditionData) {
        return new Condition(
            this._createEntity(conditionData['entity.name']),
            this._createOperator(conditionData['operator.name']),
            conditionData.valueParse
        );
    }

    _createEntity(entityName) {
        return entityFactory.create(entityName, this.field);
    }

    _createOperator(operatorName) {
        return operatorFactory.create(operatorName.toUpperCase());
    }
}

/*------------------------ Rule ------------------------*/

class Rule {
    constructor() {
        this.conditions = [];
    }

    addCondition(condition) {
        if (condition) this.conditions.push(condition);
    }

    check() {
        for (const key in this.conditions) {
            if (!this.conditions[key].check()) {
                return false;
            }
        }
        return true;
    }
}

/* ------------------------ Conditions -------------------------- */

class Condition {
    constructor(entity, operator, value) {
        this.entity = entity;
        this.operator = operator;
        this.value = value;
    }

    check() {
        return this.operator.checkData(this.value, this.entity.getValues());
    }
}

/* ------------------------ Entities -------------------------- */

const entityFactory = {
    create(entityName, field) {
        switch (entityName) {
            case Entity.ENTITY_FIELD_TYPE():
                return new EntityFieldType(field);

            default:
                throw new Error('Unknown entity');
        }
    },
};

class Entity {
    constructor() {}

    static ENTITY_FIELD_TYPE () {
        return 'FieldType'
    }

    getValues() {
        return null;
    }
}

class EntityFieldType extends Entity {
    constructor(field) {
        super();
        this.field = field;
    }

    getValues() {
        if (!this.field) return null;
        return parseInt(this.field.formTypeFieldId);
    }
}

/* ------------------------ Operators -------------------------- */

const operatorFactory = {
    create(operatorName) {
        switch (operatorName) {
            case Operator.IN():
                return new OperatorIn();
            case Operator.EQUAL():
                return new OperatorEqual();
            default:
                throw new Error('Unknown operator');
        }
    },
};

class Operator {
    static IN() {
        return 'IN';
    }

    static EQUAL() {
        return 'EQUAL';
    }

    checkData(value, data) {
        return true;
    }
}

class OperatorIn extends Operator {
    checkData(value, data) {
        return super.checkData(value, data) && value.includes(data);
    }
}

class OperatorEqual extends Operator {
    checkData(value, data) {
        return super.checkData(value, data) && value == data;
    }
}