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

import { Injectable, NgModuleRef } from "@angular/core";
import { Route } from "@angular/router";
import { RESOURCES_ROUTE } from "../../../app/plugin-container/plugin-container.module";
import { CLOUD_RESOURCES } from "../../../extensions/routing-paths/cloud-resource.paths";
import { NSXT_GROUPS_ROUTES, ORG_NETWORKS } from "../../../extensions/routing-paths/networking-domain.paths";
import {
    DOMAIN_NETWORKING,
    NETWORK,
    ORG_VDC_NETWORK,
    VDC,
    VDC_ID_ROUTE_PARAM
} from "../../../extensions/routing-paths/vdcs-route-paths";
import { COMPONENT_SCOPE_PREFIX } from "../../../../lib-interfaces";
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";

/**
 * This scope is intended to be injected in the tenant network details
 */
export const NETWORK_DETAILS_COMPONENT_SCOPE = `${COMPONENT_SCOPE_PREFIX}:network-details`;

/**
 * Network Details manifest type (Constant)
 */
export const NETWORK_DETAILS_TYPE = "navigation:network-details";

/**
 * Network Details manifest type (Type)
 */
export type NETWORK_DETAILS_TYPE = "navigation:network-details";

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

/**
 * Network Details extension point manifests have the type of "urn:vmware:vcd:component-scope:network-details".
 * They declare a single component or full Angular module, which should be injected onto network-details sub navigation.
 */
export interface NetworkDetailsExtensionPointManifest extends ExtensionPointManifest {
    readonly type: NETWORK_DETAILS_TYPE;
    readonly component: string;
    readonly module?: string;
    readonly route?: string;
}

/**
 * Handler for the Networking Details extension points.
 * It will register the plugin modules directly in the main navigation through the plugins manager service.
 */
@Injectable()
export class NetworkDetailsExtensionPointHandler implements ExtensionPointHandler {
    constructor(
        private extensionComponentRegistry: ExtensionComponentRegistry,
        private routingHandler: ExtensionPointRoutingHandler
    ) {
    }

    supports(version: string, type: string): boolean {
        return SUPPORTED_VERSIONS.indexOf(version) != -1 && type == NETWORK_DETAILS_TYPE;
    }

    bootstrap(
        extensionBundle: any,
        extensionAngularModule: NgModuleRef<any>,
        extensionPointManifest: NetworkDetailsExtensionPointManifest,
        ordering: number,
        state: ExternalExtensionLoaderState
    ): void {
        if (!extensionPointManifest.component) {
            throw new Error("Network Details component not defined in manifest");
        }

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

        if (extensionPointManifest.module) {
            if (!vcdRoute) {
                throw new Error(`Navigation Details extension '${extensionPointManifest.component}' 
                defines a module, but no matching route was found for the registration.`);
            }

            const resourcesRouteInNetworkingOrgNetworks: Route = this.routingHandler.findRoute(DOMAIN_NETWORKING,
                [`${ORG_NETWORKS}/:${ORG_VDC_NETWORK.ID_PARAM}`, RESOURCES_ROUTE]);

            const resourcesRouteInNetworkingVdcGroups = this.routingHandler.findRoute(DOMAIN_NETWORKING,
                [`${(CLOUD_RESOURCES.VDC_GROUP)}/${NSXT_GROUPS_ROUTES.NSXT}/:${CLOUD_RESOURCES.VDC_GROUP_ID}`,
                    `${NSXT_GROUPS_ROUTES.VDC_GROUP_NETWORKS}/:${ORG_VDC_NETWORK.ID_PARAM}`, RESOURCES_ROUTE]);

            const resourcesRouteInVdcDetails = this.routingHandler.findRoute(VDC.VDCS,
                [`:${VDC_ID_ROUTE_PARAM}`, `${NETWORK.ORG_VDC_NETWORK}/:${ORG_VDC_NETWORK.ID_PARAM}`,
                    RESOURCES_ROUTE]);

            const extensionName = extensionPointManifest.name;
            this.routingHandler.registerExtensionRouting(resourcesRouteInNetworkingOrgNetworks, vendor, vcdRoute, extensionName);
            this.routingHandler.registerExtensionRouting(resourcesRouteInNetworkingVdcGroups, vendor, vcdRoute, extensionName);
            this.routingHandler.registerExtensionRouting(resourcesRouteInVdcDetails, vendor, vcdRoute, extensionName);
        }

        const registration = new ExtensionComponentRegistration(
            NETWORK_DETAILS_COMPONENT_SCOPE,
            extensionAngularModule,
            null,
            null,
            [],
            ordering,
            extensionPointManifest,
            state.manifest.locales,
            extensionPointManifest.module ? vcdRoute : null,
            getHashedString(vendor)
        );

        this.extensionComponentRegistry.registerExtensionComponent(registration);
    }
}
