import { Observable, of, Subscription, from } from 'rxjs';
import { EXTENSION_ACTION_TYPES } from '../../constants';
import { ofType } from 'redux-observable';
import { mergeMap, map } from 'rxjs/operators';
import { TestScheduler } from 'rxjs/testing';
import { TextDocumentPositionParams, TextDocumentRegistrationOptions } from 'vscode-languageserver-protocol';
import {
    DocumentFeatureProviderRegistry as AbstractDocumentFeatureProviderRegistry,
    Entry,
    FeatureProviderRegistry as AbstractFeatureProviderRegistry,
} from '@workbench-stack/extension-api';
import 'jest';
import ApolloClient from 'apollo-client';
import { REGISTER_PROVIDER_QUERY } from '../queries';
import { PROVIDER_DEFINITION_MUTATION, UPDATE_MODEL_MUTATION } from '../mutations';
import { IController, IServices } from '@workbench-stack/extension-api';
import { client } from './apollo-client-test-helper';


const context: { controller: { services: Pick<IServices, 'model'> } } =
{
    controller: {
        services: {
            model: {
                model:
                    { next: (val) => val as any } as any,
            },
        },
    },
};


// const schema1 = makeExecutableSchema({ typeDefs: defaultSchema2 });

// const schema = makeExecutableSchema({ typeDefs: defaultSchema.concat(typeDefs), resolvers: resolver });

/** Useful text fixtures. */
export const FIXTURE = {
    TextDocumentPositionParams: {
        position: { line: 1, character: 2 },
        textDocument: { uri: 'file:///f' },
    } as TextDocumentPositionParams,
    TextDocumentPositionParams2: {
        position: { line: 2, character: 3 },
        textDocument: { uri: 'file:///f1' },
    } as TextDocumentPositionParams,

    PartialEntry: {
        registrationOptions: {
            documentSelector: ['*'],
        } as TextDocumentRegistrationOptions,
    },
};


class FeatureProviderRegistry extends AbstractFeatureProviderRegistry<TextDocumentRegistrationOptions, {}> {
    public get providersSnapshot(): {}[] {
        return this.entries.value.map(({ provider }) => provider);
    }
}

xdescribe('FeatureProviderRegistry', () => {
    test('is initially empty', () => {
        expect(new FeatureProviderRegistry().providersSnapshot).toEqual([]);
    });

    test('registers and unregisters providers', () => {
        const subscriptions = new Subscription();
        const registry = new FeatureProviderRegistry();
        const provider1 = () => ({});
        const provider2 = () => ({});

        const unregister1 = subscriptions.add(
            registry.registerProvider(FIXTURE.PartialEntry.registrationOptions, provider1),
        );
        expect(registry.providersSnapshot).toEqual([provider1]);

        const unregister2 = subscriptions.add(
            registry.registerProvider(FIXTURE.PartialEntry.registrationOptions, provider2),
        );
        expect(registry.providersSnapshot).toEqual([provider1, provider2]);

        unregister1.unsubscribe();
        expect(registry.providersSnapshot).toEqual([provider2]);

        unregister2.unsubscribe();
        expect(registry.providersSnapshot).toEqual([]);
    });
});


// console.log('--clinet', client);
describe('FeatureProviderRegistry', () => {
    test('registers and unregisters providers', async () => {
        const provider1 = () => ({});
        const provider2 = () => ({});

        await client.query({
            query: REGISTER_PROVIDER_QUERY,
            variables: { registrationOptions: FIXTURE.PartialEntry.registrationOptions, provider: FIXTURE.TextDocumentPositionParams },
        });
        console.log('---next');
        await client.query({
            query: REGISTER_PROVIDER_QUERY,
            variables: { registrationOptions: FIXTURE.PartialEntry.registrationOptions, provider: FIXTURE.TextDocumentPositionParams2 },
        });
        console.log('---end');

    });

    test('providerDefinition', async () => {
        const result = await client.mutate({
            mutation: PROVIDER_DEFINITION_MUTATION,
            variables: { test1: 'test1' },
            context: context,
        });

        console.log(result);
    });

    test('model', async (done) => {

        try {
            await client.mutate({
                mutation: UPDATE_MODEL_MUTATION,
                variables: {
                    model: {
                        roots: {
                            url: '//file:root',
                        },
                        visibleViewComponents: [{
                            type: 'textEditor',
                            item: {
                                uri: '//file:subfile',
                                languageId: 'json',
                                text: '{test: false}',
                            },
                            isActive: false,
                        }],
                    },
                },
                context: context,
            });
            done();
        } catch (err) {
            done.fail();
        }
    });
});
