import 'reflect-metadata';
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,
    FeatureProviderRegistry as AbstractFeatureProviderRegistry,
} from '@workbench-stack/extension-api';
import { resolvers } from './resolvers';
import { makeExecutableSchema, addMockFunctionsToSchema } from 'graphql-tools';
import { editorSchema as typeDefs } from './schema';
import 'jest';
import ApolloClient from 'apollo-client';
import { SchemaLink } from 'apollo-link-schema';
import { REGISTER_PROVIDER_QUERY } from './queries';
import { PROVIDER_DEFINITION_MUTATION } from './mutations';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { withClientState } from 'apollo-link-state';
import { ApolloLink } from 'apollo-link';

const cache = new InMemoryCache();
const context = { contextTest: 'context' }
const defaultSchema = `
type Query {
    dummy: Int
}
type Mutation {
    dummy: Int
}
`;
const defaultSchema2 = `
type Query {
    dummy1: Int
}
type Mutation {
    dummy1: Int
}
`;

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

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

/** 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([]);
    });
});
const schemaLink = new SchemaLink({
    schema: schema1,
    context: context,
});
const linkState = withClientState({
    cache,
    resolvers: resolvers,
    typeDefs: defaultSchema.concat(typeDefs),
});
const links = [linkState, schemaLink];

// const client = new ApolloClient({
//     withClientState({
//         cache,
//         resolvers: resolver,
//         typeDefs: defaultSchema.concat(typeDefs),
//     cache: new InMemoryCache(),
// });
const client = new ApolloClient({
    queryDeduplication: true,
    // dataIdFromObject: (result) => modules.getDataIdFromObject(result),
    link: ApolloLink.from(links),
    cache,
});

// 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: { contextMutationt: 'hey'}
        });

        console.log(result);
    });
});

