const chokidar = require('chokidar') // 使用chokidar监听文件变化
const bodyParser = require('body-parser') // 使用body-parser作为请求体解析中间件
const chalk = require('chalk')
const path = require('path')

const mockDir = path.join(process.cwd(), 'mock')

// 注册路由
function registerRoutes(app) {
  let mockLastIndex
  const { default: mocks } = require('./index.js')
  for (const mock of mocks) {
    app[mock.type](mock.url, mock.response)
    mockLastIndex = app._router.stack.length
  }
  const mockRoutesLength = Object.keys(mocks).length
  return {
    mockRoutesLength: mockRoutesLength,
    mockStartIndex: mockLastIndex - mockRoutesLength
  }
}

// 清除路由缓存
function unregisterRoutes() {
  Object.keys(require.cache).forEach(i => {
    if (i.includes(mockDir)) {
      delete require.cache[require.resolve(i)]
    }
  })
}

module.exports = app => {
  require('@babel/register') // es6 polyfill
  // parse app.body(https://expressjs.com/en/4x/api.html#req.body)
  app.use(bodyParser.json()) // 解析 application/json
  app.use(bodyParser.urlencoded({ // 解析 application/x-www-form-urlencoded
    extended: true
  }))
  const mockRoutes = registerRoutes(app)
  var mockRoutesLength = mockRoutes.mockRoutesLength
  var mockStartIndex = mockRoutes.mockStartIndex

  // 通过chokidar来观察mock文件夹内容的变化，在发生变化时会清除之前注册的mock-api接口，重新动态挂载新的接口，从而支持热更新
  chokidar.watch(mockDir, {
    ignored: /mock-server/,
    ignoreInitial: true
  }).on('all', (event, path) => {
    if (event === 'change' || event === 'add') {
      try {
        app._router.stack.splice(mockStartIndex, mockRoutesLength) // 移除mock路由堆栈 
        unregisterRoutes() // 清除路由缓存
        const mockRoutes = registerRoutes(app)
        mockRoutesLength = mockRoutes.mockRoutesLength
        mockStartIndex = mockRoutes.mockStartIndex
        console.log(chalk.magentaBright(`\n > Mock Server 热重载成功! changed  ${path}`))
      } catch (error) {
        console.log(chalk.redBright(error))
      }
    }
  })
}
