import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { fork } from 'redux-saga/effects';

import { Provider } from 'react-redux';
import { ConnectedRouter } from 'react-router-redux';
import * as injectTapEventPlugin from 'react-tap-event-plugin';
import { Store } from 'redux';

import createSagaMiddleware, { SagaMiddleware } from 'redux-saga';

import Platform from '@overflow/commons/platform';
import AppContext from '@overflow/commons/context';
import * as AppContextLifecycleActions from '@overflow/commons/context/redux/action/lifecycle';
import WebSocketRPC from '@overflow/commons/websocket/WebSocketRPC';
import { History } from 'history';
import { store, sagaMiddleware, history } from './redux/store';

import appConfig, { Config } from './config';

import sagas from './redux/saga';
// import routes from './router';

import {Layout} from './views/layout/Layout';

injectTapEventPlugin();

const rpcURL = 'ws://127.0.0.1:18081/rpc';


class App {
  private config: Config;
  private container: HTMLElement;
  private context: AppContext;
  private rpcClient: WebSocketRPC;
  private store: Store<any>;
  private sagaMiddleware: SagaMiddleware<any>;
  private history: History;

  public constructor() {
    this.config = appConfig;
    this.sagaMiddleware = sagaMiddleware;
    this.store = store;
  }

  public async start(): Promise<void> {
    try {
      this.container = await Platform.getAppContainer(this.config.container.placeholderID);
      this.displayLoading();

      this.context = await this.initContext();
      // this.rpcClient = await this.initRpcClient();
      await this.initSagaEffect();

      this.store.dispatch(AppContextLifecycleActions.initialized());

      this.displayApp();
    } catch (e) {
      this.displayError(e);
    }
  }

  public initContext(): Promise<AppContext> {
    const appContext = new Promise<AppContext>(resolve => {
      const context = AppContext.getContext();
      resolve(context);
    });

    return appContext;
  }

  public initRpcClient(): Promise<WebSocketRPC> {
    const rpcClient = new Promise<WebSocketRPC>((resolve, reject) => {
      let client = new WebSocketRPC(this.config.rpc.url);
      client.initialize()
        .then(() => {
          resolve(client);
        })
        .catch((err: any) => {
          reject(err);
        });
    });

    return rpcClient;
  }

  public initSagaEffect(): Promise<void> {
    const rpcClient = new Promise<void>(resolve => {
      this.sagaMiddleware.run(sagas);
      resolve();
    });

    return rpcClient;
  }


  private displayLoading(): void {
    ReactDOM.render(
        <div style={{
          width: '100vw',
          height: '100vh',
          backgroundColor: 'white',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
          }}>
            <h1>Loading...</h1>
        </div>,
        this.container,
    );
  }

  private displayError(e: Error): void {
    ReactDOM.render(
        <div style={{
          width: '100vw',
          height: '100vh',
          backgroundColor: 'white',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
          }}>
            <h1>{e.message}</h1>
        </div>,
        this.container,
    );
  }


  private displayApp(): void {
    ReactDOM.render(
      <div><Layout /></div>,
      this.container,
    );
  }

}

let app = new App();
app.start();

