"use strict";

require('isomorphic-fetch')

const http = require('http')
    , React = require('react')
    , Immutable = require('immutable')
    , thunk = require('redux-thunk').default
    , { createStore, applyMiddleware } = require('redux')
    , { Provider } = require('react-redux')
    , { renderToString } = require('react-dom/server')

const Router = require('./router')
    , rootReducer = require('./reducers')
    , Root = require('./components/root.jsx')
    , Application = require('./components/application.jsx')
    , { navigateToPath } = require('./actions')
    , { version } = require('../package.json')
    , { ApplicationState } = require('./records/state')


function render(html, renderClient=true) {
  const jsFilename = global.DEVELOPMENT_MODE ?
    'editorsnotes.js' :
    `editorsnotes-${version}.min.js`

  const cssFilename = jsFilename.replace(/.js$/, '.css')

  return `<!doctype html>
<html lang="en">
  <head>
    <title>Editors' Notes</title>
    <meta charset="utf-8"/>
    <link rel="stylesheet" href="/static/${cssFilename}" />
  </head>

  <body>
    ${html}
    ${!renderClient ? '' : `<script src="/static/${jsFilename}" type="text/javascript"></script>`}
  </body>
</html>
`
}

module.exports = {
  serve(port, apiURL, developmentMode) {
    global.API_URL = apiURL;
    global.DEVELOPMENT_MODE = developmentMode;

    const jed = require('./jed')()
        , router = new Router()
        , initialState = new ApplicationState({ jed })

    const server = http.createServer((req, res) => {
      const store = createStore(
        rootReducer,
        initialState,
        applyMiddleware(thunk)
      )

      store.dispatch(navigateToPath(router, req.url, req))
        .promise
        .then(() => {
          let bodyHTML

          try {
            const applicationHTML = renderToString(<Root store={store} />)

            const bootstrap = store
              .getState()
              .toMap()
              .filter((val, key) => key !== 'jed')

            bodyHTML = `
    <div id="react-app" style="height: 100%">
      ${applicationHTML}
    </div>
    <script type="text/javascript">
      window.EDITORSNOTES_BOOTSTRAP = ${JSON.stringify(bootstrap, true, '  ')};
    </script>
            `


          } catch (e) {
            const fakeStore = createStore(() => Immutable.Map(), Immutable.Map())

            const ErrorComponent = () => (
              <div>
                <h1>Server error</h1>
                <pre className="p2">{ e.stack }</pre>
              </div>
            )

            const fakeRouter = {
              match: () => ({
                handler: {
                  Component: ErrorComponent
                }
              })
            }

            bodyHTML = renderToString(
              <Provider store={fakeStore}>
                <Application router={fakeRouter} />
              </Provider>
            )

            process.stderr.write(e.stack + '\n');
          }

          res.writeHead(200, { 'Content-Type': 'text/html' });
          res.end(render(bodyHTML));
        })
        .catch(err => {
          // It should never get here, right?
          throw err;
        })
    });

    server.listen(port);
    return server;
  }
}

@@ -1522,24 +1522,56 @@
 , res) =%3E %7B%0A
+      const start = new Date();%0A
       const 
@@ -1591,16 +1591,16 @@
 eStore(%0A
-
         
@@ -1796,16 +1796,110 @@
 dyHTML%0A%0A
+          let msg = %60%5B$%7Bstart.toDateString()%7D $%7Bstart.toLocaleTimeString()%7D%5D GET $%7Breq.url%7D%60%0A%0A
         
@@ -2371,17 +2371,48 @@
      %60%0A%0A
+            msg += ' (200 OK) '
 %0A
-
         
@@ -2664,16 +2664,177 @@
  %7D%3C/pre%3E
+%0A%0A                %3Ch2%3EStore state%3C/h2%3E%0A                %3Cpre className=%22p2%22%3E%0A                %7BJSON.stringify(store.getState(), true, '  ')%7D%0A                %3C/pre%3E
 %0A       
@@ -3213,32 +3213,67 @@
 %0A            )%0A%0A
+            msg += ' (500 ERROR) '%0A
             proc
@@ -3309,32 +3309,197 @@
 n');%0A          %7D
+%0A          const html = render(bodyHTML);%0A%0A          msg += %60$%7BbodyHTML.length%7D $%7Bnew Date().getTime() - start.getTime()%7Dms%5Cn%60;%0A%0A          process.stdout.write(msg);
 %0A%0A          res.
@@ -3565,32 +3565,20 @@
 res.end(
-render(bodyHTML)
+html
 );%0A     

Improve server logging