import * as React from 'react';
import ReactDOM from 'react-dom';
import { AppContainer } from 'react-hot-loader';
import defaultsDeep from 'lodash-es/defaultsDeep';

import { initializeIntl } from 'mweb/client/initializeIntl';
import { setupClientStoreAfterRender } from 'mweb/client/setupClientStoreAfterRender';
import configureStore from 'mweb/common/stores/configureStore';
import { LatencyReporter } from 'mweb/common/latency/latencyReporter';
import { App, AppProps } from 'mweb/client/app';
import {
  getOrCreateDeviceID,
  getOrCreateSessionID,
} from 'mweb/common/utils/uniqueIDs';
import { RootState } from 'mweb/common/reducers/root';
import { getNetInfo } from 'mweb/common/actions/platform';
import { BRANCH_PROD_KEY } from 'mweb/common/config/branch';
import { initializeBranch } from 'branch-io';
import { setupClientErrorHandling, logger } from 'tachyon-logger';

function addDeviceInfoToPreloadedState(preloadedState: RootState): RootState {
  const device = {
    deviceID: getOrCreateDeviceID(),
    sessionID: getOrCreateSessionID(),
    netInfo: getNetInfo(),
  };
  return defaultsDeep({ device }, preloadedState) as RootState;
}

const state = addDeviceInfoToPreloadedState(window.__PRELOADED_STATE__);
const store = configureStore(state);
const latencyReporter = new LatencyReporter(store);

try {
  // Necessary for communicating with player for things like selenium tests.
  window.document.domain = 'twitch.tv';
} catch (e) {
  logger.error(e);
}

if (process.env.NODE_ENV !== 'production') {
  (window as any).store = store;
}
const { app: { gitHash }, device: { deviceID, sessionID } } = store.getState();
logger.log(`Starting app version: ${gitHash}`);

initializeIntl();

// Import the branch fetcher and setup branch.
initializeBranch(BRANCH_PROD_KEY, {
  no_journeys: true,
});

function renderApp(Component: React.ComponentClass<AppProps>): void {
  (ReactDOM as any).hydrate(
    <AppContainer>
      <Component store={store} latencyReporter={latencyReporter} />
    </AppContainer>,
    document.getElementById('app'),
  );
}

renderApp(App);
if ((module as any).hot) {
  (module as any).hot.accept('mweb/client/app', () => {
    renderApp(App);
  });
}

setupClientStoreAfterRender(store);
setupClientErrorHandling(gitHash, deviceID, sessionID);
