import https from 'https';
import fs from 'fs';
import express from 'express';
import path from 'path';
import React from 'react';
import compression from 'compression';
import exphbs from 'express-handlebars';
import { match, RouterContext, browserHistory } from 'react-router';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import { IntlProvider } from 'react-intl';
import CssBaseline from '@material-ui/core/CssBaseline';

import { SheetsRegistry } from 'react-jss/lib/jss';
import JssProvider from 'react-jss/lib/JssProvider';
import {
  MuiThemeProvider,
  createMuiTheme,
  createGenerateClassName,
} from '@material-ui/core/styles';
import ReactDOMServer from 'react-dom/server';
import themeObject from '../style/theme';

import config from '../config';
import { absAssetUrl } from './utils';
import clientRoutes from '../client/routes';
import initialState from '../client/redux/initialState';
import rootReducers from '../client/redux/rootReducers';
import { IntlConfigProvider } from '../client/components/Intl/Intl';
import localeConfig from '../../locales/ar-sy/ar-sy_config.json';
import localeLang from '../../locales/ar-sy/ar-sy_lang.json';
import template from './views/template.handlebars';

const manifest = process.env.NODE_ENV === 'production'
  ? require('./dist/public/manifest') // eslint-disable-line import/no-unresolved
  : { 'app.css': 'css/base.css', 'app.js': 'js/app.js', 'vendor.js': 'js/vendor.js' };

const scriptSrcs = [
  absAssetUrl(manifest['vendor.js']),
  absAssetUrl(manifest['app.js']),
];
const cssHrefs = [
  absAssetUrl(manifest['app.css']),
];

const PORT = config.get('server.port');
const PRIVATE_KEY = fs.readFileSync(path.resolve(__dirname, config.get('server.tlsKey')), 'utf8');
const CERTIFICATE = fs.readFileSync(path.resolve(__dirname, config.get('server.tlsCert')), 'utf8');
const credentials = { key: PRIVATE_KEY, cert: CERTIFICATE };

const locale = {
  config: localeConfig,
  messages: localeLang,
};

const app = express();

// create redux store
const store = createStore(rootReducers, initialState);

const initialData = {
  __LOCALE__: locale,
  __UI_CONFIG__: {
    env: config.get('env'),
    authService: {
      url: config.get('authService.url')
    },
    medicalConsultationService: {
      url: config.get('medicalConsultationService.url')
    }
  },
  // __INITIAL_STATE__: store.getState(),
};
const createInitialData = data => Object.keys(data)
  .map(key => `\nwindow.${key}=${JSON.stringify(data[key])};`)
  .join('');

app.use(compression());

if (process.env.NODE_ENV === 'production') {
  app.use(express.static(path.join(__dirname, 'dist/public')));
} else {
  /* eslint-disable global-require */
  const webpackDevMiddleware = require('webpack-dev-middleware');
  const webpackHotMiddleware = require('webpack-hot-middleware');
  const webpack = require('webpack');
  const webpackConfig = require('../../webpack.config');
  /* eslint-enable */
  const compiler = webpack(webpackConfig);
  app.use(webpackDevMiddleware(compiler, { serverSideRender: true }));
  app.use(webpackHotMiddleware(compiler));
}

app.engine('handlebars', exphbs({ defaultLayout: 'template' }));
app.set('view engine', 'handlebars');

app.get('*', (req, res, next) => {
  match(
    { history: browserHistory, routes: clientRoutes, location: req.url },
    (err, redirectLocation, renderProps) => {
      let htmlString = '';

      if (renderProps) {
        const sheetsRegistry = new SheetsRegistry();
        const sheetsManager = new Map();
        // Create a theme instance in client side as well
        const theme = createMuiTheme(themeObject);

        const generateClassName = createGenerateClassName();

        htmlString = ReactDOMServer.renderToString(
          <JssProvider registry={sheetsRegistry} generateClassName={generateClassName}>
            <MuiThemeProvider theme={theme} sheetsManager={sheetsManager}>
              <CssBaseline />
              <Provider store={store}>
                <IntlConfigProvider config={locale.config}>
                  <IntlProvider messages={locale.messages} locale={locale.config.localeCode}>
                    <RouterContext {...renderProps} />
                  </IntlProvider>
                </IntlConfigProvider>
              </Provider>
            </MuiThemeProvider>
          </JssProvider>
        );

        const cssServerSide = sheetsRegistry.toString();
        res.send(template({
          scripts: scriptSrcs,
          css: cssHrefs,
          initialData: createInitialData(initialData),
          body: htmlString,
          title: 'Healthcare App',
          cssServerSide
        }));
        res.end();
      }

      next();
    }
  );
});

const httpsServer = https.createServer(credentials, app);

httpsServer.listen(PORT);
console.log(`Secure server is Up and Running at Port :  ${PORT}`); // eslint-disable-line no-console
