import { BehaviorSubject, Observable, Unsubscribable } from 'rxjs';
import { map, withLatestFrom, mergeMap, combineLatest, tap } from 'rxjs/operators';
import { TextDocumentRegistrationOptions } from 'vscode-languageserver-protocol';
import { TextDocumentIdentifier, getModeFromPath , match} from '@workbench-stack/extension-api';
import { ApolloClient } from 'apollo-client';
import { ofType } from 'redux-observable';
import { EXTENSION_ACTION_TYPES } from '../constants';
import { EXTENSION_REGISTRY_QUERY } from '../graphql/queries';
import { from } from 'zen-observable';


/** A registry entry for a registered provider. */
export interface Entry<O, P> {
    registrationOptions: O;
    provider: P;
}

/**
 * A registry for providers that provide features within a document. Use this class instead of
 * {@link FeatureProviderRegistry} when all calls to the providers are scoped to a document.
 *
 * For example, hovers are scoped to a document (i.e., the document URI is one of the required arguments passed to
 * the hover provider), so this method is used for the hover provider registry.
 */
/**
 * @param document The text document to find applicable providers for.
 * @param filter An optional function to filter providers based on their registration options.
 * @returns an observable of the set of registered providers that apply to the document. The observable emits
 * initially and whenever the set changes (due to a provider being registered or unregistered).
 */
// export function getDocumentProviders<O>(
//     entries, document: TextDocumentIdentifier,
//     filter?: (registrationOptions: O) => boolean) {
//     return entries
//         .filter(
//             ({ registrationOptions }) =>
//                 (filter ? filter(registrationOptions) : true) &&
//                 match(registrationOptions.documentSelector, {
//                     uri: document.uri,
//                     languageId: getModeFromPath(document.uri),
//                 }),
//         )
//         .map(({ provider }) => provider);
// }


/** A registry entry for a registered provider. */
export interface Entry<O, P> {
    registrationOptions: O;
    provider: P;
}

/**
 * A registry for providers that provide features within a document. Use this class instead of
 * {@link FeatureProviderRegistry} when all calls to the providers are scoped to a document.
 *
 * For example, hovers are scoped to a document (i.e., the document URI is one of the required arguments passed to
 * the hover provider), so this method is used for the hover provider registry.
 */
/**
 * @param document The text document to find applicable providers for.
 * @param filter An optional function to filter providers based on their registration options.
 * @returns an observable of the set of registered providers that apply to the document. The observable emits
 * initially and whenever the set changes (due to a provider being registered or unregistered).
 */
// export function getDocumentProviders<O>(
//     entries, document: TextDocumentIdentifier,
//     filter?: (registrationOptions: O) => boolean) {
//     return entries
//         .filter(
//             ({ registrationOptions }) =>
//                 (filter ? filter(registrationOptions) : true) &&
//                 match(registrationOptions.documentSelector, {
//                     uri: document.uri,
//                     languageId: getModeFromPath(document.uri),
//                 }),
//         )
//         .map(({ provider }) => provider);
// }


// export function getProviders<O, P>(entries: Entry<O, P>[] | any) {
//     return entries.map(({ provider }) => provider);
// }
export function getDocumentProviders<O, P>(apolloClient: ApolloClient<any>) {
    return from(apolloClient.watchQuery({
        query: '',
    }).pipe(
        map(entries =>
            entries.filter(
                ({ registrationOptions }) =>
                    (filter ? filter(registrationOptions) : true) &&
                    match(registrationOptions.documentSelector, {
                        uri: document.uri,
                        languageId: getModeFromPath(document.uri),
                    }),
            )
                .map(({ provider }) => provider),
        ));
}


export function getProviders<O, P>(apolloClient: ApolloClient<any>) {
    return from(apolloClient.watchQuery({
        query: '',
    }).pipe(map(({ provider }) => provider)));
}
export function registerProvider<O, P>(apolloClient: ApolloClient<any>, registrationOptions: O, provider: P) {
    apolloClient.writeQuery({
        query: '',
        data: { registrationOptions },
    });
}

export function registerProviders<O, P>(apolloClient: ApolloClient<any>, entries: Entry<O, P>[] | any) {
    apolloClient.writeQuery({
        query: '',
        data: { entries },
    });
}



