
import InteractionFactory from "../domain/InteractionFactory";
import IStepParser from "../domain/IStepParser";
import SequenceEvaluation from "../domain/SequenceEvaluation";
import SequenceEvaluator from "../domain/SequenceEvaluator";
import SequenceEvaluatorRepository from "../domain/SequenceEvaluatorRepository";
import StepFactory from "../domain/StepFactory";

export default class SequenceEvaluationApplication {

    public sequenceEvaluatorRepository: SequenceEvaluatorRepository;
    private stepFactory: StepFactory;

    constructor(sequenceEvaluatorRepository: SequenceEvaluatorRepository, stepParser: IStepParser) {
        this.sequenceEvaluatorRepository = sequenceEvaluatorRepository;
        this.stepFactory = new StepFactory(stepParser);
    }

    public createSequenceEvaluator(webSiteId: string, stepList: Array<{name: string, expression: string, forbiddenInteractionList: string[]}>): Promise<void> {
        
        return this.sequenceEvaluatorRepository.createSequenceEvaluator(webSiteId, this.stepFactory, stepList)
            .then((_sequenceEvaluator) => {return; });
    }

    public updateSequenceEvaluator(webSiteId: string, stepList: Array<{name: string, expression: string, forbiddenInteractionList: string[]}>): Promise<void> {
        return this.sequenceEvaluatorRepository.updateSequenceEvaluator(webSiteId, stepList)
        .then(() => {return; });
    }

    public removeSequenceEvaluator(webSiteId: string): Promise<void> {
        return this.sequenceEvaluatorRepository.removeSequenceEvaluator(webSiteId)
        .then(() => {return; });
    }

    public getSequenceEvaluator(webSiteId: string): Promise<SequenceEvaluator> {
        if (webSiteId === undefined || webSiteId === null) {
            return Promise.resolve(null);
        }
        return this.sequenceEvaluatorRepository.getSequenceEvaluatorByWebSiteId(webSiteId, this.stepFactory).then((evaluator) => {
            return evaluator;
        });
    }

    public evaluateSequence(webSiteId: string, sequence: string[]): Promise<SequenceEvaluation | null> {
        const interactionList = sequence.map((interactionText) => InteractionFactory.parseInteraction(interactionText));
        return this.sequenceEvaluatorRepository.getSequenceEvaluatorByWebSiteId(webSiteId, this.stepFactory)
        .then((evaluator) => {
            if (!evaluator) {
                return null;
            }
            return evaluator.evaluate(interactionList);
        });
    }

    public checkExpressionValidity(expression: string): Promise<boolean> {
        return this.stepFactory.checkExpressionValidity(expression)
    }


    public expressionToDot(expression: string): Promise<string> {
        return this.stepFactory.createStep("Expression", expression, []).then((step) => {
            return step.stepDFA.toDot("Expression");
        })
    }

}
