import RuleService from "../domain/rules/RuleService";
import BackgroundMessageService from "./BackgroundMessageService";
import Rule from "../domain/rules/Rule";

export default class EventListenerApplication {
    ruleService: RuleService;
    handledEvents: string[];
    newActionCallbacks: Function[];
    backgroundMessageService: BackgroundMessageService;

    constructor(ruleService: RuleService, backgroundMessageService: BackgroundMessageService) {
        this.ruleService = ruleService
        this.handledEvents = [];
        this.newActionCallbacks = [];
        this.backgroundMessageService = backgroundMessageService;
        this.exploratoryListener = this.exploratoryListener.bind(this);
    }

    exploratoryListener(event): Promise<void> {
        if (!event.explored) {
            event.explored = true;
            const listenedElement = this.ruleService.getListenedElements(event)
            return this.ruleService.getMatchingRules(event, listenedElement).then((rules: Rule[])  => {
                if (rules && rules.length > 0) {
                    for (const rule of rules) {
                        const action = rule.makeAction(event, listenedElement);
                        if (action) {
                            return this.backgroundMessageService.sendAction(action).then(() => {
                                this.newActionCallbacks.forEach(callback => callback(action));
                            })
                            
                        } else return Promise.resolve();
                    }
                }
            })
        } else {
            return Promise.resolve()
        }
    }

    addNewActionCallback(callback) {
        if (typeof callback === "function") {
            this.newActionCallbacks.push(callback)
        }
    }

    adaptToWebSite(webSite) {
        this.handledEvents = [];
        webSite.mappingList.forEach((mapping) => {
            let event = mapping.match.event;
            if (!this.handledEvents.includes(event)) {
                this.handledEvents.push(event);
            }
        });
    }

    unlisten() {
        this.handledEvents.forEach((handledEvent) => {
            window.removeEventListener(handledEvent, this.exploratoryListener, true)
        });
    }

    listen() {
        const events = this.ruleService.getEventsToHandle()
        this.handledEvents = events;
        this.handledEvents.forEach((handledEvent) => {
            window.addEventListener(handledEvent, this.exploratoryListener, true)
        });
    }

    onExplorationStarted(): Promise<void> {
        this.listen();
        return Promise.resolve();
    }

    onExplorationStopped(): Promise<void> {
        this.unlisten()
        return Promise.resolve();
    }

    onReload(): Promise<void> {
        this.unlisten();
        this.listen();
        return Promise.resolve();
    }

}
