'use strict'

const fs = require('graceful-fs')
const path = require('path')
const helper = require('./helper')

const log = require('./logger').create('plugin')

const IGNORED_PACKAGES = ['karma-cli', 'karma-runner.github.com']

function resolve (plugins, emitter) {
  const modules = []

  function requirePlugin (name) {
    log.debug(`Loading plugin ${name}.`)
    try {
      modules.push(require(name))
    } catch (e) {
      if (e.code === 'MODULE_NOT_FOUND' && e.message.includes(name)) {
        log.error(`Cannot find plugin "${name}".\n  Did you forget to install it?\n  npm install ${name} --save-dev`)
      } else {
        log.error(`Error during loading "${name}" plugin:\n  ${e.message}`)
      }
      emitter.emit('load_error', 'plug_in', name)
    }
  }

  plugins.forEach(function (plugin) {
    if (helper.isString(plugin)) {
      if (!plugin.includes('*')) {
        requirePlugin(plugin)
        return
      }
      const pluginDirectory = path.normalize(path.join(__dirname, '/../..'))
      const regexp = new RegExp(`^${plugin.replace(/\*/g, '.*').replace(/\//g, '[/\\\\]')}`)

      log.debug(`Loading ${plugin} from ${pluginDirectory}`)
      fs.readdirSync(pluginDirectory)
        .map((e) => {
          const modulePath = path.join(pluginDirectory, e)
          if (e[0] === '@') {
            return fs.readdirSync(modulePath).map((e) => path.join(modulePath, e))
          }
          return modulePath
        })
        .reduce((a, x) => a.concat(x), [])
        .map((modulePath) => path.relative(pluginDirectory, modulePath))
        .filter((moduleName) => !IGNORED_PACKAGES.includes(moduleName) && regexp.test(moduleName))
        .forEach((pluginName) => requirePlugin(path.join(pluginDirectory, pluginName)))
    } else if (helper.isObject(plugin)) {
      log.debug(`Loading inline plugin defining ${Object.keys(plugin).join(', ')}.`)
      modules.push(plugin)
    } else {
      log.error(`Invalid plugin ${plugin}`)
      emitter.emit('load_error', 'plug_in', plugin)
    }
  })

  return modules
}

/**
  Create a function to handle errors in plugin loading.
  @param {Object} injector, the dict of dependency injection objects.
  @return function closed over injector, which reports errors.
*/
function createInstantiatePlugin (injector) {
  const emitter = injector.get('emitter')
  // Cache to avoid report errors multiple times per plugin.
  const pluginInstances = new Map()
  return function instantiatePlugin (kind, name) {
    if (pluginInstances.has(name)) {
      return pluginInstances.get(name)
    }

    let p
    try {
      p = injector.get(`${kind}:${name}`)
      if (!p) {
        log.error(`Failed to instantiate ${kind} ${name}`)
        emitter.emit('load_error', kind, name)
      }
    } catch (e) {
      if (e.message.includes(`No provider for "${kind}:${name}"`)) {
        log.error(`Cannot load "${name}", it is not registered!\n  Perhaps you are missing some plugin?`)
      } else {
        log.error(`Cannot load "${name}"!\n  ` + e.stack)
      }
      emitter.emit('load_error', kind, name)
    }
    pluginInstances.set(name, p, `${kind}:${name}`)
    return p
  }
}

createInstantiatePlugin.$inject = ['injector']

module.exports = { resolve, createInstantiatePlugin }
