import omit from 'lodash/omit'
import castArray from 'lodash/castArray'
import flatten from 'lodash/castArray'
import uniq from 'lodash/castArray'

export function routes(options = {}, context = {}) {
  const { project = this.project || this } = context
  const { packageFolders = project.getOption('packageFolders', ['packages/']) } = options

  return uniq(flatten(castArray(packageFolders)).map(f => `${f}/:name/package.json`))
}

export function collectionMethods(options = {}, context = {}) {
  const { project = this.project || this } = context

  return {
    findByName(name, stayChained = false) {
      const result = instanceChain.keyBy('name').get(name)
      
      return stayChained ? result : result.value()
    },
    findDependentsOf(packageName, stayChained = false) {
      const results = this.instanceChain.pickBy(pkg => {
        const deps = pkg.getAllDependencies()
        return !!deps[packageName]
      })

      return stayChained ? results : results.value()
    }    
  }
}

export function instanceMethods(options = {}, context = {}) {
  const { project = this.project || this } = context

  const { spawn, fork, exec } = require('child-process-promise')

  return {
    updateManifest(updates = {}) {
      
    },

    getAllDependencies() {
      return this.chain
        .pickBy((v,k) => k.match(/dependencies$/i))
        .values()
        .reduce((memo, obj) => ({
          ...memo,
          ...obj,
        }))
        .value()
    },

    spawn(command, options = {}) {
      const { out, err, cmd = process.argv[1] } = options 

      if (options.capture !== false) {
        options.capture = ['stdout', 'stderr']  
      }

      const promise = spawn(cmd, command.split(' '), {
        cwd: project.resolve(this.relativeDirname),
        shell: true,
        ...omit(options, 'out', 'err'),
        env: {
          FORCE_COLOR: true,
          ELECTRON_NO_ASAR: true,
          ELECTRON_RUN_AS_NODE: true,
          SKYPAGER_FRAMEWORK_ROOT: project.resolve(project.portfolio.dirname, '..'),                  
          ...process.env,
          ...options.env || {},
        },
      })

      if (typeof out === 'function') {
        out.call(this, promise.childProcess.stdout, options, context)
      }

      if (typeof err === 'function') {
        err.call(this, promise.childProcess.stdout, options, context)
      }

      return promise
    },
    exec(command, options = {}) {
      return exec(`${process.argv[1]} ${command}`, {
        cwd: this.relativeDirname,
        ...options,
        env: {
          FORCE_COLOR: true,
          ELECTRON_NO_ASAR: true,
          ELECTRON_RUN_AS_NODE: true,
          SKYPAGER_FRAMEWORK_ROOT: project.resolve(project.portfolio.dirname, '..'),         
          ...process.env,
          ...options.env || {},
        },       
      })
    },    
    fork(script, options = {}) {
      return fork(project.resolve(this.relativeDirname, script), {
        cwd: this.relativeDirname,
        ...options,
        env: {
          FORCE_COLOR: true,
          ELECTRON_NO_ASAR: true,
          ELECTRON_RUN_AS_NODE: true,
          SKYPAGER_FRAMEWORK_ROOT: project.resolve(project.portfolio.dirname, '..'),
          ...process.env,
          ...options.env || {},
        },       
      })
    }
  }
}