import { System } from "../../../../ecs/System.js";
import { PathDisplay } from "../PathDisplay.js";
import Highlight from "../../highlight/Highlight.js";
import { PathDisplayEvents } from "../PathDisplayEvents.js";
import { PathDisplaySystem } from "../PathDisplaySystem.js";

export class PathDisplayHighlightSystem extends System {
    constructor() {
        super();

        this.dependencies = [PathDisplay, Highlight];
    }

    /**
     *
     * @param {number} entity
     * @returns {PathDisplayContext|undefined}
     * @private
     */
    __getPathDisplayContext(entity) {

        /**
         *
         * @type {PathDisplaySystem}
         */
        const pds = this.entityManager.getSystem(PathDisplaySystem);

        if (pds === null) {
            console.warn('PathDisplaySystem not registered');
            return;
        }
        /**
         *
         * @type {PathDisplayContext}
         */
        const ctx = pds.__getEntityContext(entity);

        return ctx;
    }

    /**
     *
     * @param _
     * @param {number} entity
     * @private
     */
    __apply_to_entity(_, entity) {
        const ecd = this.entityManager.dataset;

        const highlight = ecd.getComponent(entity, Highlight);

        if (highlight === undefined) {
            console.error(`Entity ${entity} no longer has a Highlight`);
            return;
        }

        const ctx = this.__getPathDisplayContext(entity);

        if (ctx === undefined) {
            // no context
            return;
        }

        /**
         *
         * @type {Entity[]}
         */
        const ownedEntities = ctx.__owned_entities;

        for (let i = 0; i < ownedEntities.length; i++) {
            const eb = ownedEntities[i];

            if (eb.hasComponent(Highlight)) {
                //already has a highlight
                console.warn(`Owned entity ${eb.id} of PathDisplay entity ${entity} already has a Highlight component attached. Keeping existing Highlight.`);
                continue;
            }

            eb.add(highlight);
        }
    }

    /**
     *
     * @param _
     * @param {number} entity
     * @private
     */
    __remove_from_entity(_, entity) {
        const ecd = this.entityManager.dataset;

        const highlight = ecd.getComponent(entity, Highlight);

        if (highlight === undefined) {
            console.error(`Entity ${entity} no longer has a Highlight`);
            return;
        }

        const ctx = this.__getPathDisplayContext(entity);

        if (ctx === undefined) {
            // no context
            return;
        }

        /**
         *
         * @type {Entity[]}
         */
        const ownedEntities = ctx.__owned_entities;

        for (let i = 0; i < ownedEntities.length; i++) {
            const eb = ownedEntities[i];

            const hl = eb.getComponent(Highlight);

            if (hl !== highlight) {
                // has a different highlight, leave alone
                continue;
            }

            eb.removeComponent(Highlight);
        }
    }

    link(display, highlight, entity) {
        this.__apply_to_entity(null, entity);

        const ecd = this.entityManager.dataset;

        ecd.addEntityEventListener(entity, PathDisplayEvents.BuildComplete, this.__apply_to_entity, this);
    }

    unlink(display, highlight, entity) {
        const ecd = this.entityManager.dataset;

        ecd.removeEntityEventListener(entity, PathDisplayEvents.BuildComplete, this.__apply_to_entity, this);

        this.__remove_from_entity(null, entity);
    }
}
