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

import { Injectable, NgModuleRef, Type } from "@angular/core";
import { COMPONENT_SCOPE_PREFIX } from "../../../../lib-interfaces";
import { ExtensionPointManifest } from "../extensibility.model";
import { ExtensionComponentRegistration, ExtensionComponentRegistry } from "../extension-component.registry";
import { ExtensionPointHandler } from "../extension-point.handler";
import { ExternalExtensionLoaderState } from "../loader/extension-loader.model";
import { getHashedString } from "../loader/external/create-external-extension-route.step";
import { EntityActionExtensionComponent } from "./entity-action-extension.component";

/**
 * This prefix is for scopes intended to be injected in entity pages
 */
export const ENTITY_ACTION_COMPONENT_SCOPE_PREFIX = `${COMPONENT_SCOPE_PREFIX}:entity-action`;

/**
 * This scope is for injecting into VM pages (i.e. with <ng-container vcdExtensionComponents scope="...">)
 */
export const VM_ACTION_COMPONENT_SCOPE = `${ENTITY_ACTION_COMPONENT_SCOPE_PREFIX}:vm`;

/**
 * This scope is for injecting into vApp pages (i.e. with <ng-container vcdExtensionComponents scope="...">)
 */
export const VAPP_ACTION_COMPONENT_SCOPE = `${ENTITY_ACTION_COMPONENT_SCOPE_PREFIX}:vapp`;

/**
 * VM action manifest type (constant value)
 */
export const VM_ACTION_TYPE = "vm-action";

/**
 * VM action manifest type (type value)
 */
export type VM_ACTION_TYPE = "vm-action";

/**
 * vApp action manifest type (constant value)
 */
export const VAPP_ACTION_TYPE = "vapp-action";

/**
 * VM action manifest type (type value)
 */
export type VAPP_ACTION_TYPE = "vapp-action";

/**
 * All entity action types.
 */
export type ENTITY_ACTION_TYPE = VM_ACTION_TYPE | VAPP_ACTION_TYPE;

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

/**
 * Dashboard Section extension point manifests have the type of e.g. "vapp-action", "vm-action".
 * They declare a single component, which should be injected onto the entity's screen.
 */
export interface EntityActionExtensionPointManifest extends ExtensionPointManifest {
    readonly type: ENTITY_ACTION_TYPE;
    readonly component: string;
}

/**
 * This extension point handler supports extension manifests of version 9.5.0 and of type
 * "vm-action" or "vapp-action".  It will register the defined component with the ExtensionComponentRegistry
 * under the scope of "urn:vmware:vcd:component-scope:entity-action:[vapp,vm]".  This scope is intended to be
 * injected in the entity pages (i.e. with <ng-container vcdExtensionComponents scope="...">)
 */
@Injectable()
export class EntityActionExtensionPointHandler implements ExtensionPointHandler {
    constructor(private extensionComponentRegistry: ExtensionComponentRegistry) {}

    /**
     * Supports version 9.5.0 and type "{vm,vapp}-action".
     */
    supports(version: string, type: string): boolean {
        return SUPPORTED_VERSIONS.indexOf(version) != -1 && (type == VM_ACTION_TYPE || type == VAPP_ACTION_TYPE);
    }

    /**
     * Register the defined component with the ExtensionComponentRegistry under the scope of
     * "urn:vmware:vcd:component-scope:entity-action:{vm,vapp}".  Will assert the component defined
     * inherits from EntityActionComponent.
     */
    bootstrap(
        extensionBundle: any,
        extensionAngularModule: NgModuleRef<any>,
        extensionPointManifest: EntityActionExtensionPointManifest,
        ordering: number,
        state?: ExternalExtensionLoaderState
    ): void {
        if (!extensionPointManifest.component) {
            throw new Error("Entity action component not defined in manifest");
        }

        // const component: Type<any> = extensionBundle[extensionPointManifest.component];
        // if (!component) {
        //     throw new Error(
        //         `Entity action component '${extensionPointManifest.component}' ` + "not exported by extension bundle"
        //     );
        // }

        // if (!Object.prototype.isPrototypeOf.call(EntityActionExtensionComponent.prototype, component.prototype)) {
        //     throw new Error(
        //         `Entity action component '${extensionPointManifest.component}' ` +
        //             "not inheriting from EntityActionComponent base class"
        //     );
        // }

        const scope =
            extensionPointManifest.type == "vapp-action" ? VAPP_ACTION_COMPONENT_SCOPE : VM_ACTION_COMPONENT_SCOPE;
        const registration = new ExtensionComponentRegistration(
            scope,
            extensionAngularModule,
            // state.angularModuleFactories[`${state.spec.id}:${extensionPointManifest.urn}`],
            null,
            // component,
            null,
            [],
            ordering,
            extensionPointManifest,
            state.manifest.locales,
            null,
            getHashedString(state.manifest.vendor)
        );
        this.extensionComponentRegistry.registerExtensionComponent(registration);
    }
}
