import {
  DEPENDENCIES_FIELDS,
  PackageJson,
} from '@pnpm/types'
import R = require('ramda')
import {
  Shrinkwrap,
} from './types'

export default (shr: Shrinkwrap, pkg: PackageJson, importerId: string) => {
  const importer = shr.importers[importerId]
  if (!importer) return false
  if (!R.equals({ ...pkg.devDependencies, ...pkg.dependencies, ...pkg.optionalDependencies }, importer.specifiers)) {
    return false
  }
  for (const depField of DEPENDENCIES_FIELDS) {
    const importerDeps = importer[depField] || {}
    const pkgDeps = pkg[depField] || {}

    let pkgDepNames!: string[]
    switch (depField) {
      case 'optionalDependencies':
        pkgDepNames = Object.keys(pkgDeps)
        break
      case 'devDependencies':
        pkgDepNames = Object.keys(pkgDeps)
          .filter((depName) =>
            (!pkg.optionalDependencies || !pkg.optionalDependencies[depName]) &&
            (!pkg.dependencies || !pkg.dependencies[depName])
          )
        break
      case 'dependencies':
        pkgDepNames = Object.keys(pkgDeps)
          .filter((depName) => !pkg.optionalDependencies || !pkg.optionalDependencies[depName])
        break
      default:
        throw new Error(`Unknown dependency type "${depField}"`)
    }
    if (pkgDepNames.length !== Object.keys(importerDeps).length &&
      pkgDepNames.length !== countOfNonLinkedDeps(importerDeps)) {
      return false
    }
    for (const depName of pkgDepNames) {
      if (!importerDeps[depName] || importer.specifiers[depName] !== pkgDeps[depName]) return false
    }
  }
  return true
}

function countOfNonLinkedDeps (shrDeps: {[depName: string]: string}): number {
  return R.values(shrDeps).filter((ref) => ref.indexOf('link:') === -1 && ref.indexOf('file:') === -1).length
}
