// Copyright (C) 2017 The Bazel Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package build.bazel.ci

import hudson.FilePath
import hudson.remoting.Channel
import org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper

/**
 * This class provide utility methods of the Jenkins API
 */
class JenkinsUtils {
  /** A list of regex aliases to know that ubuntu is linux */
  private static def NODE_ALIASES = [
    "ubuntu.*": "linux-x86_64",
    "docker.*": "linux-x86_64",
    "darwin.*": "darwin-x86_64",
  ]

  /** Normalize the node label into a compatible platform */
  // TODO(dmarting): does that really belongs here?
  @NonCPS
  static def normalizeNodeLabel(node_label) {
    for (e in NODE_ALIASES) {
      if (node_label.matches(e.key)) {
        return e.value
      }
    }
    return node_label
  }

  /** Returns the list of all slave' names */
  @NonCPS
  static def nodeNames() {
    return jenkins.model.Jenkins.instance.nodes.collect { node -> node.name }
  }

  /** Returns the list of job in the folder `folderName` (empty or null for top folder). */
  @NonCPS
  private static def folderJobs(folderName) {
    if (folderName == null || folderName.isEmpty()) {
      return jenkins.model.Jenkins.instance.items
    } else {
      return jenkins.model.Jenkins.instance.getItemByFullName(folderName).getAllJobs()
    }
  }

  /**
   * Returns the list of names of jobs in the folder `folderName` (empty or null for the
   * top folder).
   */
  @NonCPS
  static def jobs(folderName) {
    return folderJobs(folderName).collect { job -> job.name }
  }

  /**
   * Returns the list of names of jobs in the folder `folder` (empty or null for the top
   * folder) whose description contains the string `descr`
   */
  @NonCPS
  static def jobsWithDescription(folder, descr) {
    def items = jenkins.model.Jenkins.instance.items
    def jobs = folderJobs(folder)
    return jobs.findAll {
      job -> job.description != null && job.description.contains(descr) }.collect {
      job -> job.name }
  }

  /** Returns the last build of a job in a specific folder */
  @NonCPS
  static def getLastRun(folder, job) {
    def j = folderJobs(folder).find { it -> it.name.equals(job) }
    if (j != null) {
      def run = j.getLastCompletedBuild()
      if (run != null) {
        return new org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper(run, false)
      }
    }
    return null
  }

  /** Returns the URL of the console for a job run */
  static def getConsoleUrl(RunWrapper run) {
    return "${run.absoluteUrl}console"
  }

  /** Returns the URL of the blue ocean view for a job run */
  @NonCPS
  static def getBlueOceanUrl(RunWrapper run) {
    def name = java.net.URLEncoder.encode(run.fullProjectName, "UTF-8")
    def url = new URL(run.absoluteUrl)
    def path = "/blue/organizations/jenkins/${name}/detail/${run.projectName}/${run.number}/pipeline/"
    return new URL(url.protocol, url.host, url.port, path).toString()
  }

  /** Returns the URL to the small icon for a run */
  @NonCPS
  static def getSmallIconUrl(RunWrapper run) {
    return "${Jenkins.RESOURCE_PATH}/images/16x16/${run.rawBuild.getIconColor()}.png"
  }

  /**
   * A utility method that look for an artifact matching a pattern in upstream
   * builds.
   */
  @NonCPS
  static def findAndCopyUpstreamArtifacts(run, pattern) {
    def build = findLastBuildWithUpstream(run.rawBuild)
    if (build == null) {
      return null
    }
    return _findAndCopyUpstreamArtifacts(build.getCauses(), pattern)
  }

  @NonCPS
  private static def _findAndCopyUpstreamArtifacts(causes, pattern) {
    for (cause in causes) {
      if (cause instanceof Cause.UpstreamCause) {
        def upstreamRun = cause.getUpstreamRun()
        def artifacts = upstreamRun.getArtifacts()
        for (artifact in artifacts) {
          if (artifact.toString().matches(pattern)) {
            return [artifactPath: artifact.toString(),
                    artifactName: artifact.getFileName(),
                    upstreamBuild: cause.getUpstreamBuild(),
                    upstreamProject: cause.getUpstreamProject()]
          }
        }
        def res = _findAndCopyUpstreamArtifacts(cause.upstreamCauses, pattern)
        if (res != null && !res.isEmpty()) {
          return res;
        }
      }
    }
    return null
  }

  /**
   * Find the latest build that was run by upstream.
   * In case of re-run, the current build will not be triggered by upstream project.
   * In that case we want to look at build history to fetch the latest one that was build
   * with upstream.
   */
  @NonCPS
  private static def findLastBuildWithUpstream(run) {
    while (run != null) {
      if (run.getCauses().any { it.class.toString().contains("UpstreamCause") }) {
        return run
      }
      run = run.getPreviousBuild()
    }
    return run
  }

  @NonCPS
  private static def _pruneIfOlderThan(file, timestamp) throws IOException {
    if (file.isDirectory()) {
      boolean empty = true
      for (child in file.list()) {
        if (!_pruneIfOlderThan(child, timestamp)) {
          empty = false
        }
      }
      if (empty) {
        if (file.delete()) {
          return true
        }
      }
    } else if (file.lastModified() < timestamp) {
      if (file.delete()) {
        return true
      }
    }
    return false
  }

  @NonCPS
  private static def createFilePath(env, path) {
    if (env['NODE_NAME'].equals("master")) {
        return new FilePath(path);
    } else {
        return new FilePath(Jenkins.getInstance().getComputer(env['NODE_NAME']).getChannel(), path);
    }
  }

  /** Prune file that are older than timestamp on the current node. */
  @NonCPS
  public static def pruneIfOlderThan(env, path, timestamp) {
    return _pruneIfOlderThan(createFilePath(env, path), timestamp)
  }

  /** Touch a file anywhere on the FS on the current node. */
  @NonCPS
  public static def touchFileIfExists(env, path) {
    FilePath f = createFilePath(env, path)
    def r = f.exists()
    if (r) {
      try {
        f.touch(System.currentTimeMillis())
      } catch(IOException ex) {
        // The file might be busy, especially on windows, swallowing exception
      }
    }
    return r;
  }

  /** Read a file from the node, but without reporting anything in the Jenkins UI. */
  @NonCPS
  public static def readFile(env, path) {
    return createFilePath(env, path).readToString()
  }

  /** Save the current log to a file on the current node. */
  @NonCPS
  public static void saveLog(env, RunWrapper run, path) {
    createFilePath(env, path).copyFrom(run.getRawBuild().getLogInputStream())
  }

  /** Returns the recursive list of files of a folder, ignoring some files. */
  @NonCPS
  public static def list(env, dir, excludes) {
    def directory = createFilePath(env, dir)
    def results = directory.list("**", excludes.join(","))
    def directoryUri = directory.toURI()
    return results.collect { it -> directoryUri.relativize(it.toURI()) }
  }
}
