import { combineLatest, from, Observable, Subject, Subscription, Unsubscribable, of } from 'rxjs';
import { distinctUntilChanged, map, share, switchMap, tap, pluck, switchAll } from 'rxjs/operators';
import { IController } from '@workbench-stack/extension-api';
import { Services } from '../services/services';
import { logger } from '@cdm-logger/client';
import { createConnection, IClientInitData, PlatformContext, Contributions } from '@workbench-stack/extension-api';
import { createExtensionHostClient } from './extension-client';
import { ContributionRegistry } from '../api/providers/contribution';
import { isErrorLike } from '../util/errors';
import { ExtensionManifest } from './extension-manifest';
import { IClientService as IWorkbenchService } from '@workbench-stack/core';



process = global.process;
/**
 * Creates the controller, which handles all communication between the client application and extensions.
 *
 * There should only be a single controller for the entire client application. The controller's model represents
 * all of the client application state that the client needs to know.
 */
export function createController(context: PlatformContext, internalService: IWorkbenchService): IController {
    console.log('[check>>>]: createController ----', global.process);
    const subscriptions = new Subscription();

    const services = new Services(context, internalService);
    const extensionHostConnection = combineLatest(
        context.createExtensionHost().pipe(
            switchMap(async messageTransports => {
                const connection = createConnection(messageTransports);
                connection.listen();

                const initData: IClientInitData | any = {
                    cdecodeURL: context.cdecodeURL,
                    clientApplication: context.clientApplication,
                    graphqlSubscriptionUrl: global.process.APP_ENV ? global.process.APP_ENV.GRAPHQL_SUBSCRIPTION_URL : global.process.env.GRAPHQL_SUBSCRIPTION_URL,
                    extensionSocketUrl: global.process.APP_ENV ? global.process.APP_ENV.EXTENSION_SOCKET_URL : global.process.env.EXTENSION_SOCKET_URL,
                };
                await connection.sendRequest('initialize', [initData]);
                return connection;
            }),
            share(),
        ),
        context.traceExtensionHostCommunication,
    ).pipe(
        tap(([connection, trace]) => connection.trace(trace ? logger : null)),
        map(([connection]) => connection),
        distinctUntilChanged(),
    );
    const client = createExtensionHostClient(services, extensionHostConnection);
    console.log('Controller client', client);
    subscriptions.add(client);
    subscriptions.add(registerExtensionContributions(services.contribution, services.extensions));

    const notifications = new Subject<Notification>();

    // subscriptions.add(registerExtensionCon)

    function messageFromExtension(message: string): string {
        return `From extension:\n\n${message}`;
    }

    return {
        notifications,
        services,
        unsubscribe: () => subscriptions.unsubscribe(),
    } as any;
}


// function registerExtensionContributions(
//     contributionRegistry: ContributionRegistry,
//     { activeExtensions }: Pick<ExtensionsService, 'activeExtensions'>,
function registerExtensionContributions(
    contributionRegistry: ContributionRegistry,
    { activeExtensions }: Pick<any, 'activeExtensions'>,
): Unsubscribable {
    const contributions = from(activeExtensions)
    .pipe(
        switchMap(
            (extensions: any[]) => combineLatest(
                ...extensions
                    .map(
                        ext => of(ext).pipe(
                                pluck('manifest', 'contributes'),
                                tap(contributes => console.log({ contributes })),
                            ),
                        ),
            ),
        ),
    );

    return contributionRegistry.registerContributions({
        contributions,
    });
}

