import * as React from 'react';
import { createPlatformContext } from '../platform/context';
import { createController } from '../extensions/controller';
import { from as observableFrom } from 'rxjs';
import { ApolloClient } from 'apollo-client';
import {
  PlatformContextProps,
  IExtensionsControllerProps,
  PlatformContext,
  IController,
} from '@workbench-stack/extension-api';
import { ExtensionContext } from '@workbench-stack/components';
import { ExtensionViewSlot } from '../containers/ExtensionViewSlot';
import { getApolloContext } from 'react-apollo';
import { ReactReduxContext } from 'react-redux';
import { useService } from '@workbench-stack/module-browser';
import { IClientService as IService, LifecyclePhase } from '@workbench-stack/core';
export namespace ExtensionApp {
  export interface IProps {
    client?: ApolloClient<any>;
    store?: any;
    modules?: any;
  }

  export interface IState
    extends PlatformContextProps,
      IExtensionsControllerProps {}
}

/**
 * ExtensionApp listens to a connection object passed from props.
 * When a connection object is changed, it dispatches action to redux store.
 * Then, store will pass props to component to render.
 */
export const ExtensionApp: React.FC<ExtensionApp.IProps> = ({ children }) => {
  const [controller, setController] = React.useState<IController>();
  const { client } = React.useContext(getApolloContext());
  const { store } = React.useContext(ReactReduxContext);
  const service = useService<IService>();
  // runs after the component is mounted.
  React.useEffect(() => {
    const storeRxjsObservable$ = observableFrom(store as any);
    const pltContext = createPlatformContext(
      client,
      storeRxjsObservable$,
      store,
    );
    if (service && pltContext) {
      const ctrl = createController(pltContext, service);
      setController(ctrl);

      // Signal to lifecycle that services are set
      // service.lifecycleService.phase = LifecyclePhase.Ready;
    }
    // need to subscribe and unsubscribe something like this
    // this.unsubscribe = storeRxjsObservable$.subscribe(() => {

    // });
    return () => {
      // this.unsubscribe();
    };
  }, []);
  return (
    <ExtensionContext.Provider value={{ controller }}>
      <>
        {children}
        {controller && <ExtensionViewSlot />}
      </>
    </ExtensionContext.Provider>
  );
};
