import { from, Subscription } from 'rxjs';
import { bufferCount, startWith, map, tap } from 'rxjs/operators';
import { createProxyAndHandleRequests, WebExtHostExtensionServiceShape,
    Connection, IExtensionsService,
    IExecutableExtension } from '@workbench-stack/extension-api';
import { isEqual } from 'lodash';


export class ClientExtensions {
    private subscriptions = new Subscription();
    private proxy: WebExtHostExtensionServiceShape;

    /**
     * Implements the client side of extensions API.
     *
     * @param connection The connection to the extension host.
     * @param extensionRegistry An observable that emits the set of extensions that should be activated
     *                          upon subscription and whenever it changes.
     */
    constructor(connection: Connection, extensionRegistry: IExtensionsService) {
        this.proxy = createProxyAndHandleRequests('extensions', connection, this);
        this.subscriptions.add(
            from(extensionRegistry.activeExtensions)
                .pipe(
                    startWith([] as IExecutableExtension[]),
                    // bufferCount(2, 1),
                    tap((e) => console.log('registrate', e)),
                    // map((event: any) => event.payload),
                )
                .subscribe((extensions: any[]) => {
                    // Diff next state's activated extensions vs. current state's.
                    const toActivate = [...extensions ]; // cli to avoid mutating state stored by bufferCount
                    const toDeactivate: IExecutableExtension[] = [];
                    const next: IExecutableExtension[] = [];

                    // if (oldExtensions) {
                    //     for (const x of oldExtensions) {
                    //         const newIndex = toActivate.findIndex(({ id }) => isEqual(x.id, id));
                    //         if (newIndex === -1) {
                    //             // Extension is no longer activated
                    //             toDeactivate.push(x);
                    //         } else {
                    //             // Extension is already activated.
                    //             toActivate.splice(newIndex, 1);
                    //             next.push(x);
                    //         }
                    //     }
                    // }

                    /**
                     * Deactive extensions that are no longer in use. In practice,
                     * {@link activeExtensions} never deactivates extensions, so this will never be
                     * called (in the current implementation).
                     */
                    for (const x of toDeactivate) {
                        this.proxy.$deactivateExtension(x.id).catch(err => {
                            console.warn(`Error deactivating extension ${JSON.stringify(x.id)}:`, err);
                        });
                    }

                    // Activate extensions that haven't yet been activated.
                    for (const x of toActivate) {
                        this.proxy
                            .$activateExtension(x.id, x.scriptURL)
                            .catch(err => console.error(`Error activating extension ${JSON.stringify(x.id)}:`, err));
                    }
                }),
        );
    }

    public unsubscribe(): void {
        this.subscriptions.unsubscribe();
    }
}
