/*
 * Copyright 2020-2025 VMware, Inc. All rights reserved. VMware Confidential
 */

import { Injectable, NgModuleRef } from "@angular/core";
import { RESOURCES_ROUTE } from "../../../app/plugin-container/plugin-container.module";
import { VDC, VDC_ID_ROUTE_PARAM } from "../../../extensions/routing-paths/vdcs-route-paths";
import { ExtensionPointManifest } from "../extensibility.model";
import { ExtensionComponentRegistration, ExtensionComponentRegistry } from "../extension-component.registry";
import { ExtensionPointRoutingHandler } from "../extension-point-routing.handler";
import { ExtensionPointHandler } from "../extension-point.handler";
import { ExternalExtensionLoaderState } from "../loader/extension-loader.model";
import { getHashedString } from "../loader/external/create-external-extension-route.step";
import { COMPONENT_SCOPE_PREFIX } from "../../../../lib-interfaces";

/**
 * Datacenter manifest type (constant value)
 */
export const DETAILS_CONTAINER_TYPES = [
    "navigation:datacenter:compute",
    "navigation:datacenter:network",
    "navigation:datacenter:storage",
];

/**
 * Datacenter manifest type (type value)
 */
export type DETAILS_CONTAINER_TYPES = [
    "navigation:datacenter:compute",
    "navigation:datacenter:network",
    "navigation:datacenter:storage"
];

/**
 * The manifest versions this is supported by.
 */
export const SUPPORTED_VERSIONS: string[] = ["9.5.0"];

/**
 * Datacenter Section extension point manifests have the type of @{DETAILS_CONTAINER_TYPES}.
 * They declare a single component, which should be injected onto the datacenter screen.
 */
export interface DetailsContainerExtensionPointManifest extends ExtensionPointManifest {
    readonly type: string;
    readonly component: string;
}

/**
 * This extension point handler supports extension manifests of version 9.5.0 and of type
 * @{DETAILS_CONTAINER_TYPES}.  It will register the defined component with the ExtensionComponentRegistry
 * under the scope of "urn:vmware:vcd:component-scope:${DETAILS_CONTAINER_TYPES}".  This scope is intended to be
 * injected in the datacenter (i.e. with <ng-container vcdExtensionComponents scope="...">)
 */
@Injectable()
export class DetailsContainerExtensionPointHandler implements ExtensionPointHandler {

    constructor(private extensionComponentRegistry: ExtensionComponentRegistry,
                private routingHandler: ExtensionPointRoutingHandler) {
    }

    /**
     * Supports version 9.5.0 and type @{DETAILS_CONTAINER_TYPES}.
     */
    supports(version: string, type: string): boolean {
        return SUPPORTED_VERSIONS.indexOf(version) != -1 && DETAILS_CONTAINER_TYPES.indexOf(type) != -1;
    }

    /**
     * Register the defined component with the ExtensionComponentRegistry under the scope of
     * "urn:vmware:vcd:component-scope:${DETAILS_CONTAINER_TYPES}".
     */
    bootstrap(
        extensionBundle: any,
        extensionAngularModule: NgModuleRef<any>,
        extensionPointManifest: DetailsContainerExtensionPointManifest,
        ordering: number,
        state: ExternalExtensionLoaderState
    ): void {
        if (!extensionPointManifest.component) {
            throw new Error("Datacenter component not defined in manifest");
        }

        const vcdRoute = state.routes[`${state.spec.id}:${extensionPointManifest.urn}`];

        if (extensionPointManifest.module) {
            this.routingHandler.registerExtensionRouting(
                this.routingHandler.findRoute(VDC.VDCS, [`:${VDC_ID_ROUTE_PARAM}`, RESOURCES_ROUTE]),
                state.manifest.vendor, vcdRoute, extensionPointManifest.name);
        }

        const registration = new ExtensionComponentRegistration(
            `${COMPONENT_SCOPE_PREFIX}:${extensionPointManifest.type}`,
            extensionAngularModule,
            null,
            null,
            [],
            ordering,
            extensionPointManifest,
            state.manifest.locales,
            extensionPointManifest.module ? vcdRoute : null,
            getHashedString(state.manifest.vendor)
        );

        this.extensionComponentRegistry.registerExtensionComponent(registration);
    }
}
