const path = require('path')
const webpack = require('webpack')
const MFS = require('memory-fs')
const clientConfig = require('./webpack.client.config')
const serverConfig = require('./webpack.server.config')

module.exports = function setupDevServer (app, cb) {
  let bundle, clientManifest
  let resolve
  const readyPromise = new Promise(r => { resolve = r })
  const ready = (...args) => {
    resolve()
    cb(...args)
  }

  // modify client config to work with hot middleware
  clientConfig.entry.app = ['webpack-hot-middleware/client', clientConfig.entry.app]
  clientConfig.output.filename = '[name].js'
  clientConfig.plugins.push(
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoEmitOnErrorsPlugin()
  )

  // dev middleware
  const clientCompiler = webpack(clientConfig)
  const devMiddleware = require('webpack-dev-middleware')(clientCompiler, {
    publicPath: clientConfig.output.publicPath,
    noInfo: true
  })
  app.use(devMiddleware)
  clientCompiler.plugin('done', () => {
    const fs = devMiddleware.fileSystem
    const readFile = file => fs.readFileSync(path.join(clientConfig.output.path, file), 'utf-8')
    clientManifest = JSON.parse(readFile('vue-ssr-client-manifest.json'))
    if (bundle) {
      ready(bundle, {
        clientManifest
      })
    }
  })

  // hot middleware
  app.use(require('webpack-hot-middleware')(clientCompiler))

  // watch and update server renderer
  const serverCompiler = webpack(serverConfig)
  const mfs = new MFS()
  serverCompiler.outputFileSystem = mfs
  serverCompiler.watch({}, (err, stats) => {
    if (err) throw err
    stats = stats.toJson()
    stats.errors.forEach(err => console.error(err))
    stats.warnings.forEach(err => console.warn(err))
    const readFile = file => mfs.readFileSync(path.join(clientConfig.output.path, file), 'utf-8')

    // read bundle generated by vue-ssr-webpack-plugin
    bundle = JSON.parse(readFile('vue-ssr-server-bundle.json'))
    if (clientManifest) {
      ready(bundle, {
        clientManifest
      })
    }
  })

  return readyPromise
}

@@ -203,16 +203,156 @@
 nfig')%0A%0A
+const readFile = (fs, file) =%3E %7B%0A  try %7B%0A    return fs.readFileSync(path.join(clientConfig.output.path, file), 'utf-8')%0A  %7D catch (e) %7B%7D%0A%7D%0A%0A
 module.e
@@ -1135,18 +1135,21 @@
 'done', 
-()
+stats
  =%3E %7B%0A  
@@ -1154,140 +1154,172 @@
     
-const fs = devMiddleware.fileSystem%0A    const readFile = file =%3E fs.readFileSync(path.join(clientConfig.output.path, file), 'utf-8')
+stats = stats.toJson()%0A    stats.errors.forEach(err =%3E console.error(err))%0A    stats.warnings.forEach(err =%3E console.warn(err))%0A    if (stats.errors.length) return%0A
 %0A   
@@ -1348,32 +1348,71 @@
 .parse(readFile(
+%0A      devMiddleware.fileSystem,%0A      
 'vue-ssr-client-
@@ -1421,24 +1421,29 @@
 nifest.json'
+%0A    
 ))%0A    if (b
@@ -1851,206 +1851,39 @@
     
-stats.errors.forEach(err =%3E console.error(err))%0A    stats.warnings.forEach(err =%3E console.warn(err))%0A    const readFile = file =%3E mfs.readFileSync(path.join(clientConfig.output.path, file), 'utf-8')
+if (stats.errors.length) return
 %0A%0A  
@@ -1935,16 +1935,16 @@
 -plugin%0A
-
     bund
@@ -1968,16 +1968,21 @@
 eadFile(
+mfs, 
 'vue-ssr

improve dev server compile error handling