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

import { HttpClient } from "@angular/common/http";
import { Injectable } from "@angular/core";
import { of, Observable, throwError as _throw } from "rxjs";
import { catchError, map, tap } from "rxjs/operators";
import { ExtensionManifest, HYPER_PLUGIN_STATE, HyperPluginState, UI_PLUGINS_MANIFEST_CACHE, UiPluginsManifestCache } from "../../extensibility.model";
import { ExtensionLoaderStep, ExternalExtensionLoaderState } from "../extension-loader.model";
import { ExternalExtensionLoaderErrorObservable } from "./external-extension-loader-error";
import { logger } from "../../../../logging/logger";

export const PLUGIN_MANIFEST_URL = "/manifest.json";

@Injectable()
export class LoadExternalExtensionManifestStep implements ExtensionLoaderStep<ExternalExtensionLoaderState> {
    constructor(private http: HttpClient) {}

    /**
     * Load an extension's manifest from {extensionRoot}/manifest.json.
     * State inputs: spec
     * State outputs: manifest
     */
    public perform(state: ExternalExtensionLoaderState): Observable<ExternalExtensionLoaderState> {
        const hyperPluginState: HyperPluginState = window[HYPER_PLUGIN_STATE];
        const uiPluginManifestCache: UiPluginsManifestCache = hyperPluginState[UI_PLUGINS_MANIFEST_CACHE];

        try {
            const i18nManifestFile = state.spec.resourcePath + PLUGIN_MANIFEST_URL;
            logger.log(`[${state.spec.id}] Loading extension manifest from: ${i18nManifestFile}`);

            const cachedManifest: ExtensionManifest = uiPluginManifestCache[state.spec.id];
            if (cachedManifest) {
                return of({ ...state, manifest: cachedManifest });
            }

            return this.http.get<ExtensionManifest>(i18nManifestFile).pipe(
                tap((manifest: ExtensionManifest) =>
                    logger.log(`[${state.spec.id} (${manifest.name})] Manifest loaded`, manifest)
                ),
                map((manifest) => {
                    uiPluginManifestCache[state.spec.id] = manifest;
                    return { ...state, manifest };
                }),
                catchError((err, caught) => {
                    console.error(`[${state?.spec?.id}] Could not load manifest`, err);
                    return of({ ...state });
                })
            );
        } catch (err) {
            console.error(`[${state?.spec?.id}] Could not load manifest`, err);
            return new ExternalExtensionLoaderErrorObservable();
        }
    }
}
