import { Component } from "@angular/core";
import { CREATE_VAPP_COMPONENT_SCOPE, CREATE_VAPP_TYPE } from "../../../app/framework/common/extensibility/create-vapp/create-vapp.extension-point";
import { ExtensionComponentRegistry, ExtensionComponentRegistration } from "../../../app/framework/common/extensibility/extension-component.registry";
import { ExtensionPointOrchcestrator } from "../../../app/framework/common/extensibility/extension-point-orchestrator/extension-point.orchestrator";
import { ComponentCreatedData } from "../../../app/framework/extensions/vdcs/resources/resources.component";
import { ExtensionPointContainerWithValidation } from "../../framework/common/extensibility/extension-point-orchestrator/extension-point-container.interface";

@Component({
    selector: "create-vapp",
    templateUrl: "./create-vapp.component.html",
})
export class CreateVappComponent implements ExtensionPointContainerWithValidation {
    readonly supportedLocations = [
        {
            selector: ".vapp-name-extension-point",
            after: true,
            before: false,
        },
    ];
    readonly EXTENSION_POINT_TYPE = CREATE_VAPP_COMPONENT_SCOPE;
    readonly extensionPointsRenderRegistry = {
        after: {},
        before: {},
    };
    public internalExtensionPointType = CREATE_VAPP_TYPE;

    public showExtensions = false;

    constructor(
        private extensionComponentRegistry: ExtensionComponentRegistry,
        private extensionPointOrchcestrator: ExtensionPointOrchcestrator,
    ) {
        const timeout = setTimeout(() => {
            this.prepareExtensionPoints();
            clearTimeout(timeout);
        }, 0);
    }

    /**
     * Extension point configuration start.
     *
     * This configuration will ensure that the extension points will be rendered
     * after or before the supported location defined by us. The Plugin Writers
     * would be able to choose only from the list of supported locations.
     *
     * This limitation is needed from performance and UX perspective.
     *
     * The extension points from the type specified in CREATE_VAPP_COMPONENT_SCOPE
     * will be registered in the UI Extension Point Orchestrator, who will manage
     * when and with what payload the extension point actions will be triggered.
     */
    prepareExtensionPoints(): void {
        try {
            const extensionComponentRegistry: ExtensionComponentRegistry = this.extensionComponentRegistry;
            const extensions = extensionComponentRegistry
                .getRegisteredComponents(this.EXTENSION_POINT_TYPE)
                .sort((a: ExtensionComponentRegistration, b: ExtensionComponentRegistration) => {
                    if (a.manifest.name > b.manifest.name) {
                        return 1;
                    }
                    if (b.manifest.name > a.manifest.name) {
                        return -1;
                    }
                    return 0;
                });

            this.supportedLocations.forEach((supportedLocation) => {
                if (supportedLocation.before) {
                    this.extensionPointsRenderRegistry.before[supportedLocation.selector] = [];
                }

                if (supportedLocation.after) {
                    this.extensionPointsRenderRegistry.after[supportedLocation.selector] = [];
                }
            });

            extensions
                .filter((ext: ExtensionComponentRegistration) => {
                    return this.supportedLocations.find((supportedLocation) => {
                        return (
                            supportedLocation.selector === ext.manifest.render.before ||
                            supportedLocation.selector === ext.manifest.render.after
                        );
                    });
                })
                .forEach((ext) => {
                    try {
                        if (ext.manifest.render.before) {
                            this.extensionPointsRenderRegistry.before[ext.manifest.render.before].push(ext);
                            return;
                        }

                        if (ext.manifest.render.after) {
                            this.extensionPointsRenderRegistry.after[ext.manifest.render.after].push(ext);
                            return;
                        }
                    } catch (e) {
                        console.error(`[ExtensionPoint] Failed to activate extesion point ${ext?.manifest?.urn},
                        please check your manifest. You may use unsupported location for rendering.`);
                    }
                });
        } catch (e) {
            console.error(`[Create VApp] Unable to bootstrap Extension Points`, e);
        }

        this.showExtensions = true;
    }

    handleComponentCreation(data: ComponentCreatedData): void {
        this.extensionPointOrchcestrator.addExtensionPointCompnent(data, CREATE_VAPP_TYPE);
    }
    /**
     * Configuration End.
     */

    open = false;

    closeModal() {
        this.open = false;
    }

    openModal() {
        this.open = true;
    }
}