// 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 (optionally filtering by label) */
  @NonCPS
  static def nodeNames(label = null) {
    def nodes = jenkins.model.Jenkins.instance.nodes
    if (label != null) {
      nodes = nodes.findAll { node -> label in node.labelString.split() }
    }
    return 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 */
  @NonCPS
  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()) }
  }
}
