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

import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core";
import { ClarityModule } from "@clr/angular";
import { EXTENSION_POINT_HANDLER } from "../tokens";
import { AngularAppsExtensionPointHandler } from "./angular-apps/angular-apps.extension-point";
import { ApplicationsExtensionPointHandler } from "./applications/applications.extension-point";
import { CreateOrgExtensionPointHandler } from "./create-org/create-org.extension-point";
import { CreateVAppExtensionPointHandler } from "./create-vapp/create-vapp.extension-point";
import { CreateVMExtensionPointHandler } from "./create-vm/create-vm.extension-point";
import { DatacenterOverviewExtensionPointHandler } from "./datacenter-overview/datacenter-overview.extension-point";
import { DetailsContainerExtensionPointHandler } from "./details-container/details-container.extension-point";
import { EntityActionExtensionMenuComponent } from "./entity-action/entity-action-extension-menu.component";
import { EntityActionExtensionPointHandler } from "./entity-action/entity-action.extension-point";
import { ExtensionComponentRegistry } from "./extension-component.registry";
import { ExtensionComponentsDirective } from "./extension-components.directive";
import { ExtensionContainerComponent } from "./extension-container/extension-container.component";
import { BootstrapExtensionPointsStep } from "./loader/external/bootstrap-extension-points.step";
import { CompileExternalExtensionModuleStep } from "./loader/external/compile-external-extension-module.step";
import { CreateExternalExtensionRouteStep } from "./loader/external/create-external-extension-route.step";
import { ExternalExtensionLoader } from "./loader/external/external-extension.loader";
import { InstantiateExternalExtensionModuleStep } from "./loader/external/instantiate-external-extension-module.step";
import { LoadExternalExtensionBundleStep } from "./loader/external/load-external-extension-bundle.step";
import { LoadExternalExtensionI18nStep } from "./loader/external/load-external-extension-i18n.step";
import { LoadExternalExtensionManifestStep } from "./loader/external/load-external-extension-manifest.step";
import { RegisterExternalExtensionRoutesStep } from "./loader/external/register-external-extension-routes.step";
import { RegisterExternalExtensionTranslationsStep } from "./loader/external/register-external-extension-translations.step";
import { TopLevelNavExtensionPointHandler } from "./primary-navigation/primary-navigation.extension-point";
import { I18nModule } from "@vcd/i18n";
import { ExtensionPointOrchcestrator } from "./extension-point-orchestrator/extension-point.orchestrator";
import { ExtensionManifestLocalization } from "../display/extension-manifest-localizaton.pipe";
import { ResourceModule } from "../../extensions/vdcs/resources/resource.module";
import { ExtensionRouterLinkPipe } from "../../app/navigation/extension-router-link.pipe";
import { ExtensionApplicationsComponent } from "./extension-application.component";
import { ExtensionApplicationCustomElementsContainerComponent } from "./extension-application-custom-elements-container.component";

/**
 * This is singleton to avoid re-instantiatiation across module boundaries.
 * We explicitly only ever want _one_, global, registry.
 */
const singletonExtensionComponentRegistry = new ExtensionComponentRegistry();

export function extensionComponentRegistryFactory(): ExtensionComponentRegistry {
    return singletonExtensionComponentRegistry;
}

const exportedDeclarations = [
    ExtensionComponentsDirective,
    EntityActionExtensionMenuComponent,
    ExtensionContainerComponent,
    ExtensionManifestLocalization,
    ExtensionRouterLinkPipe,
    ExtensionApplicationsComponent,
    ExtensionApplicationCustomElementsContainerComponent,
];

@NgModule({
    imports: [I18nModule, CommonModule, ClarityModule],
    declarations: [...exportedDeclarations],
    exports: [...exportedDeclarations],
    providers: [
        CreateExternalExtensionRouteStep,
        InstantiateExternalExtensionModuleStep,
        LoadExternalExtensionBundleStep,
        CompileExternalExtensionModuleStep,
        LoadExternalExtensionI18nStep,
        LoadExternalExtensionManifestStep,
        RegisterExternalExtensionRoutesStep,
        CompileExternalExtensionModuleStep,
        RegisterExternalExtensionTranslationsStep,
        BootstrapExtensionPointsStep,
        ExternalExtensionLoader,
        {
            provide: ExtensionComponentRegistry,
            useFactory: extensionComponentRegistryFactory,
        },
        {
            provide: EXTENSION_POINT_HANDLER,
            multi: true,
            useClass: DatacenterOverviewExtensionPointHandler,
        },
        {
            provide: EXTENSION_POINT_HANDLER,
            multi: true,
            useClass: ApplicationsExtensionPointHandler,
        },
        {
            provide: EXTENSION_POINT_HANDLER,
            multi: true,
            useClass: EntityActionExtensionPointHandler,
        },
        {
            provide: EXTENSION_POINT_HANDLER,
            multi: true,
            useClass: DetailsContainerExtensionPointHandler,
        },
        {
            provide: EXTENSION_POINT_HANDLER,
            multi: true,
            useClass: TopLevelNavExtensionPointHandler,
        },
        {
            provide: EXTENSION_POINT_HANDLER,
            multi: true,
            useClass: CreateVMExtensionPointHandler,
        },
        {
            provide: EXTENSION_POINT_HANDLER,
            multi: true,
            useClass: CreateVAppExtensionPointHandler,
        },
        {
            provide: EXTENSION_POINT_HANDLER,
            multi: true,
            useClass: AngularAppsExtensionPointHandler,
        },
        {
            provide: EXTENSION_POINT_HANDLER,
            multi: true,
            useClass: CreateOrgExtensionPointHandler,
        },
        ExtensionPointOrchcestrator,
    ],
})
export class ExtensibilityModule {}
