import TaskGroup from "../core/process/task/TaskGroup.js";
import { GridTaskGenerator } from "./grid/GridTaskGenerator.js";

export class GridTaskGroup extends GridTaskGenerator {

    /**
     *
     * @type {GridTaskGenerator[]}
     */
    children = [];


    /**
     *
     * @param {GridTaskGenerator[]} children
     * @returns {GridTaskGroup}
     */
    static from(children) {
        const r = new GridTaskGroup();

        children.forEach(r.addGenerator, r);

        return r;
    }

    /**
     *
     * @param {GridTaskGenerator} generator
     */
    addGenerator(generator) {
        this.children.push(generator);
    }

    /**
     *
     * @param {EntityComponentDataset} ecd
     * @param {GridData} grid
     * @param {number} seed
     * @returns {TaskGroup}
     */
    build(grid, ecd, seed) {

        /**
         *
         * @type {(TaskGroup|Task)[]}
         */
        const tasks = [];

        const generators = this.children;
        const generator_count = generators.length;

        //generate tasks
        for (let i = 0; i < generator_count; i++) {
            const generator = generators[i];

            const task = generator.build(grid, ecd, seed);

            tasks[i] = task;
        }

        //assign dependencies
        for (let i = 0; i < generator_count; i++) {
            const generator = generators[i];

            const task = tasks[i];

            const dependencies = generator.dependencies;

            const dependencyCount = dependencies.length;

            for (let j = 0; j < dependencyCount; j++) {

                const dependency = dependencies[j];

                const dependencyIndex = generators.indexOf(dependency);

                if (dependencyIndex === -1) {
                    throw new Error(`Dependency ${j}(name='${dependency.name}') of task generator [${i}] (name='${generator.name}') is not found`);
                }

                const dependencyTask = tasks[dependencyIndex];

                task.addDependency(dependencyTask);

            }

            catchGeneratorErrors(generator, task);
        }


        return new TaskGroup(tasks, 'Grid Generator');
    }
}


/**
 *
 * @param {GridTaskGenerator} generator
 * @param {TaskGroup} task
 */
function catchGeneratorErrors(generator, task) {

    task.promise().catch(reason => {
        console.error(`Generator '${generator.name}' failed. Task status: ${task.getVerboseStatusMessage()}`);
    });

}
