import 'event-source-polyfill'
import connect from './dev-error-overlay/hot-dev-client'
import Router from 'next-server/router'

const handlers = {
  reload (route) {
    // If the App component changes we have to reload the current route, this is handled by hot-self-accept-loader
    // So we just return
    if (route === '/_app') {
      return
    }

    if (route === '/_error') {
      for (const r of Object.keys(Router.components)) {
        const { err } = Router.components[r]
        if (err) {
          // reload all error routes
          // which are expected to be errors of '/_error' routes
          Router.reload(r)
        }
      }
      return
    }

    // Since _document is server only we need to reload the full page when it changes.
    if (route === '/_document') {
      window.location.reload()
      return
    }

    Router.reload(route)
  },

  change (route) {
    // If the App component changes we have to reload the current route, this is handled by hot-self-accept-loader
    // So we just return
    if (route === '/_app') {
      return
    }

    const { err, Component } = Router.components[route] || {}

    if (err) {
      // reload to recover from runtime errors
      Router.reload(route)
    }

    if (Router.route !== route) {
      // If this is a not a change for a currently viewing page.
      // We don't need to worry about it.
      return
    }

    if (!Component) {
      // This only happens when we create a new page without a default export.
      // If you removed a default export from a exising viewing page, this has no effect.
      console.warn(`Hard reloading due to no default component in page: ${route}`)
      window.location.reload()
    }
  }
}

export default ({assetPrefix}) => {
  const options = {
    path: `${assetPrefix}/_next/webpack-hmr`
  }

  const devClient = connect(options)

  devClient.subscribeToHmrEvent((obj) => {
    const fn = handlers[obj.action]
    if (fn) {
      const data = obj.data || []
      fn(...data)
    } else {
      throw new Error('Unexpected action ' + obj.action)
    }
  })

  return devClient
}
