package com.freeleaps.devops

import com.freeleaps.devops.enums.DependenciesManager

class DependenciesResolver {
  def steps
  def language
  def cachingEnabled
  def mgr
  def workspace

  DependenciesResolver(steps, language, workspace) {
    this.steps = steps
    this.language = language
    this.workspace = workspace
  }

  def enableCachingSupport() {
    this.cachingEnabled = true
  }

  def disableCachingSupport() {
    this.cachingEnabled = false
  }

  def useManager(DependenciesManager mgr) {
    if (mgr == DependenciesManager.UNKNOWN) {
      steps.error("Unknown dependencies manager")
    }
    this.mgr = mgr
  }

  def getNodeVersion() {
    def version = steps.sh(script: "node -v", returnStdout: true).trim()
    steps.log.info 'Dependencies Resolver', "Node version is ${version}"
  }

  def resolve(configurations) {
    if (mgr == null) {
      steps.error("Dependencies manager is not set")
    }

    steps.log.info("Dependencies Resolver","Ready to resolve dependencies for ${language}...")

    steps.log.info("Dependencies Resolver","Using ${mgr.manager} to resolve dependencies...")

    steps.log.info("Dependencies Resolver","Workspace sets to: ${this.workspace}")

    if (cachingEnabled) {
      steps.log.info("Dependencies Resolver","Dependencies caching is enabled")
    }

    switch (mgr) {
      case DependenciesManager.PIP:
        if (configurations.requirementsFile == null || configurations.requirementsFile.isEmpty()) {
          steps.error("requirementsFile is required when using PIP as dependencies manager")
        }

        def requirementsFile = configurations.requirementsFile

        if (cachingEnabled) {
          // steps.dir(this.workspace) {
          //   steps.cache(maxCacheSize: 512, caches: [[$class: 'ArbitraryFileCache', includes: '**/*', path: ".${configurations.name}-pip-cache", cacheValidityDecidingFile: 'requirements.txt']]) {
          //     steps.sh "mkdir -p .${configurations.name}-pip-cache"
          //     steps.sh "pip config set global.cache-dir '${this.workspace}.${configurations.name}-pip-cache'"
          //     steps.sh "pip install --cache-dir .${configurations.name}-pip-cache -r ${requirementsFile}"
          //   }
          // }
          steps.log.info("Dependencies Resolver","Caching is not supported for PIP")
        } else {
          steps.dir(this.workspace) {
            steps.sh "pip install -r ${requirementsFile}"
          }
        }

        break
      case DependenciesManager.NPM:
        if (configurations.npmPackageJsonFile == null || configurations.npmPackageJsonFile.isEmpty()) {
          steps.error("npmPackageJsonFile is required when using NPM as dependencies manager")
        }

        def packageJsonFile = configurations.npmPackageJsonFile

        this.getNodeVersion()

        if (cachingEnabled) {
          steps.dir(this.workspace) {
            steps.cache(maxCacheSize: 2048, caches: [[$class: 'ArbitraryFileCache', includes: '**/*', path: "${steps.env.WORKSPACE}/.${configurations.name}-npm-cache", cacheValidityDecidingFile: 'package-lock.json']]) {
              steps.sh "mkdir -p ${steps.env.WORKSPACE}/.${configurations.name}-npm-cache"
              steps.sh "npm install --cache ${steps.env.WORKSPACE}/.${configurations.name}-npm-cache --prefer-offline --no-audit"
            }
          }
        } else {
          steps.dir(this.workspace) {
            steps.sh "npm install"
          }
        }

        break
      case DependenciesManager.YARN:
        if (configurations.yarnPackageJsonFile == null || configurations.yarnPackageJsonFile.isEmpty()) {
          steps.error("yarnPackageJsonFile is required when using YARN as dependencies manager")
        }

        def packageJsonFile = configurations.yarnPackageJsonFile

        this.getNodeVersion()

        steps.log.info("Dependencies Resolver","Using YARN as dependencies manager, enable Yarn with corepack...")
        steps.sh "corepack enable yarn && yarn -v"

        if (cachingEnabled) {
          steps.dir(this.workspace) {
            steps.cache(maxCacheSize: 2048, caches: [[$class: 'ArbitraryFileCache', includes: '**/*', path: "${steps.env.WORKSPACE}/.${configurations.name}-yarn-cache", cacheValidityDecidingFile: 'yarn.lock']]) {
              steps.sh "mkdir -p ${steps.env.WORKSPACE}/.${configurations.name}-pnpm-cache"
              steps.sh "yarn install --cache-folder ${steps.env.WORKSPACE}/.${configurations.name}-pnpm-cache --prefer-offline"
            }
          }
        } else {
          steps.dir(this.workspace) {
            steps.sh "yarn install"
          }
        }

        break
      case DependenciesManager.PNPM:
        if (configurations.pnpmPackageJsonFile == null || configurations.pnpmPackageJsonFile.isEmpty()) {
          steps.error("pnpmPackageJsonFile is required when using PNPM as dependencies manager")
        }

        def packageJsonFile = configurations.pnpmPackageJsonFile

        this.getNodeVersion()

        steps.log.info("Dependencies Resolver","Using pnpm as dependencies manager, enable pnpm with corepack...")
        steps.sh "corepack enable pnpm && pnpm -v"

        if (cachingEnabled) {
          steps.dir(this.workspace) {
            steps.cache(maxCacheSize: 2048, caches: [[$class: 'ArbitraryFileCache', includes: '**/*', path: "${steps.env.WORKSPACE}/.${configurations.name}-pnpm-cache", cacheValidityDecidingFile: 'pnpm-lock.yaml']]) {
              steps.sh "mkdir -p ${steps.env.WORKSPACE}/.${configurations.name}-pnpm-cache"
              steps.sh "pnpm install --store-dir ${steps.env.WORKSPACE}/.${configurations.name}-pnpm-cache --prefer-offline"
            }
          }
        } else {
          steps.dir(this.workspace) {
            steps.sh "pnpm install"
          }
        }

        break
      default:
        steps.error("Unsupported dependencies manager")
    }
  }
}