/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You 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 org.apache.toree.dependencies

import java.io.{File, FileInputStream, PrintStream}
import java.net.{URI, URL}
import java.util.Properties
import java.util.concurrent.ConcurrentHashMap
import coursier.core.Authentication
import coursier.Cache.Logger
import coursier.Dependency
import coursier.core.Repository
import coursier.core.Resolution.ModuleVersion
import coursier.ivy.{IvyRepository, IvyXml}
import coursier.maven.MavenRepository
import org.springframework.core.io.support.PathMatchingResourcePatternResolver
import scala.util.Try
import scalaz.\/
import scalaz.concurrent.Task

/**
 * Represents a dependency downloader for jars that uses Coursier underneath.
 */
class CoursierDependencyDownloader extends DependencyDownloader {
  @volatile private var repositories: Seq[Repository] = Nil
  @volatile private var printStream: PrintStream = System.out
  @volatile private var localDirectory: URI = null

  // Initialization
  setDownloadDirectory(DependencyDownloader.DefaultDownloadDirectory)
  addMavenRepository(DependencyDownloader.DefaultMavenRepository, None)

  /**
   * Retrieves the dependency and all of its dependencies as jars.
   *
   * @param groupId The group id associated with the main dependency
   * @param artifactId The id of the dependency artifact
   * @param version The version of the main dependency
   * @param transitive If true, downloads all dependencies of the specified
   *                   dependency
   * @param excludeBaseDependencies If true, will exclude any dependencies
   *                                included in the build of the kernel
   * @param ignoreResolutionErrors If true, ignores any errors on resolving
   *                               dependencies and attempts to download all
   *                               successfully-resolved dependencies
   * @param extraRepositories Additional repositories to use only for this
   *                          dependency
   * @param verbose If true, prints out additional information
   * @param trace If true, prints trace of download process
   *
   * @return The sequence of strings pointing to the retrieved dependency jars
   */
  override def retrieve(
    groupId: String,
    artifactId: String,
    version: String,
    transitive: Boolean,
    excludeBaseDependencies: Boolean,
    ignoreResolutionErrors: Boolean,
    extraRepositories: Seq[(URL, Option[Credentials])] = Nil,
    verbose: Boolean,
    trace: Boolean,
    configuration: Option[String] = None,
    artifactType: Option[String] = None,
    artifactClassifier: Option[String] = None,
    excludes: Set[(String,String)] = Set.empty
  ): Seq[URI] = {
    assert(localDirectory != null)
    import coursier._

    // Grab exclusions using base dependencies (always exclude scala lang)
    val exclusions: Set[(String, String)] = (if (excludeBaseDependencies) {
      getBaseDependencies.map(_.module).map(m => (m.organization, m.name))
    } else Nil).toSet ++ Set(("org.scala-lang", "*"), ("org.scala-lang.modules", "*")) ++ excludes

    // Mark dependency that we want to download
    val start = Resolution(Set(
      Dependency(
        module = Module(organization = groupId, name = artifactId),
        version = version,
        transitive = transitive,
        exclusions = exclusions, // NOTE: Source/Javadoc not downloaded by default
        configuration = configuration.getOrElse("default"),
        attributes = Attributes(
          artifactType.getOrElse(""),
          artifactClassifier.getOrElse("")
        )
      )
    ))

    printStream.println(s"Marking $groupId:$artifactId:$version for download")

    lazy val defaultBase = new File(localDirectory).getAbsoluteFile

    lazy val downloadLocations = defaultBase

    val allRepositories = extraRepositories.map(x => urlToMavenRepository(x._1, x._2.map(_.authentication))) ++ repositories

    // Build list of locations to fetch dependencies
    val fetchLocations = Seq(ivy2Cache(localDirectory)) ++ allRepositories
    val fetch = Fetch.from(
      fetchLocations,
      Cache.fetch(downloadLocations, logger = Some(new DownloadLogger(verbose, trace)))
    )

    val fetchUris = localDirectory +: repositoriesToURIs(allRepositories)
    if (verbose) {    
      printStream.println("Preparing to fetch from:")
      printStream.println(s"-> ${fetchUris.mkString("\n-> ")}")
    }
    // Verify locations where we will download dependencies
    val resolution = start.process.run(fetch).unsafePerformSync

    // Report any resolution errors
    val errors: Seq[(ModuleVersion, Seq[String])] = resolution.metadataErrors
    errors.foreach { case (dep, e) =>
      printStream.println(s"-> Failed to resolve ${dep._1.toString()}:${dep._2}")
      e.foreach(s => printStream.println(s"    -> $s"))
    }

    // If resolution errors, do not download
    if (errors.nonEmpty && !ignoreResolutionErrors) return Nil

    // Perform task of downloading dependencies
    val localArtifacts: Seq[FileError \/ File] = Task.gatherUnordered(
      resolution.artifacts.map(a => Cache.file(
        artifact = a,
        cache = downloadLocations,
        logger = Some(new DownloadLogger(verbose, trace))
      ).run)).unsafePerformSync

    // Print any errors in retrieving dependencies
    localArtifacts.flatMap(_.swap.toOption).map(_.message)
      .foreach(printStream.println)

    // Print success
    val uris = localArtifacts.flatMap(_.toOption).map(_.toURI)

    if (verbose) uris.map(_.getPath).foreach(p => printStream.println(s"-> New file at $p"))
    
    printStream.println("Obtained " + uris.size + " files")
    
    uris
  }

  /**
   * Adds the specified resolver url as an additional search option.
   *
   * @param url The string representation of the url
   */
  override def addMavenRepository(url: URL, credentials: Option[Credentials]): Unit =
    repositories :+= urlToMavenRepository(url, credentials.map(_.authentication))

  private def urlToMavenRepository(url: URL, credentials: Option[Authentication]) = MavenRepository(url.toString, authentication = credentials)

  /**
   * Remove the specified resolver url from the search options.
   *
   * @param url The url of the repository
   */
  override def removeMavenRepository(url: URL): Unit = {
    repositories = repositories.filterNot {
      case maven: MavenRepository => url.toString == maven.root
      case _                      => false
    }
  }

  /**
   * Sets the printstream to log to.
   *
   * @param printStream The new print stream to use for output logging
   */
  override def setPrintStream(printStream: PrintStream): Unit =
    this.printStream = printStream

  /**
   * Returns a list of all repositories used by the downloader.
   *
   * @return The list of repositories as URIs
   */
  def getRepositories: Seq[URI] = repositoriesToURIs(repositories)

  /**
   * Returns the current directory where dependencies will be downloaded.
   *
   * @return The directory as a string
   */
  override def getDownloadDirectory: String =
    new File(localDirectory).getAbsolutePath

  /**
   * Sets the directory where all downloaded jars will be stored.
   *
   * @param directory The directory to use
   * @return True if successfully set directory, otherwise false
   */
  override def setDownloadDirectory(directory: File): Boolean = {
    val path = directory.getAbsolutePath
    val cleanPath = if (path.endsWith("/")) path else path + "/"
    val dir = new File(cleanPath)

    if (!dir.exists() && !dir.mkdirs()) return false
    if (!dir.isDirectory) return false

    localDirectory = dir.toURI
    true
  }

  private class DownloadLogger(
    private val verbose: Boolean,
    private val trace: Boolean
  ) extends Logger {
    import scala.collection.JavaConverters._
    private val downloadId = new ConcurrentHashMap[String, String]().asScala
    private val downloadFile = new ConcurrentHashMap[String, File]().asScala
    private val downloadAmount = new ConcurrentHashMap[String, Long]().asScala
    private val downloadTotal = new ConcurrentHashMap[String, Long]().asScala

    override def foundLocally(url: String, file: File): Unit = {
      val id = downloadId.getOrElse(url, url)
      val f = s"(${downloadFile.get(url).map(_.getName).getOrElse("")})"
      if (verbose) printStream.println(s"=> $id: Found at ${file.getAbsolutePath}")
    }

    override def downloadingArtifact(url: String, file: File): Unit = {
      downloadId.put(url, nextId())
      val id = downloadId.getOrElse(url, url)
      val f = s"(${downloadFile.get(url).map(_.getName).getOrElse("")})"

      if (verbose) printStream.println(s"=> $id $f: Downloading $url")

      downloadFile.put(url, file)
    }

    override def downloadLength(url: String, length: Long): Unit = {
      val id = downloadId.getOrElse(url, url)
      val f = s"(${downloadFile.get(url).map(_.getName).getOrElse("")})"
      if (trace) printStream.println(s"===> $id $f: Is $length total bytes")
      downloadTotal.put(url, length)
    }

    override def downloadProgress(url: String, downloaded: Long): Unit = {
      downloadAmount.put(url, downloaded)

      val ratio = downloadAmount(url).toDouble / downloadTotal.getOrElse[Long](url, 1).toDouble
      val percent = ratio * 100.0

      if (trace) printStream.printf(
        "===> %s %s: Downloaded %d bytes (%.2f%%)\n",
        downloadId.getOrElse(url, url),
        s"(${downloadFile.get(url).map(_.getName).getOrElse("")})",
        new java.lang.Long(downloaded),
        new java.lang.Double(percent)
      )
    }

    override def downloadedArtifact(url: String, success: Boolean): Unit = {
      if (verbose) {
        val id = downloadId.getOrElse(url, url)
        val f = s"(${downloadFile.get(url).map(_.getName).getOrElse("")})"
        if (success) printStream.println(s"=> $id $f: Finished downloading")
        else printStream.println(s"=> $id: An error occurred while downloading")
      }
    }

    private val nextId: () => String = (() => {
      var counter: Long = 0

      () => {
        counter += 1
        counter.toString
      }
    })()
  }

  /**
   * Retrieves base dependencies used when building Toree modules.
   *
   * @return The collection of dependencies
   */
  private def getBaseDependencies: Seq[Dependency] = {
    import coursier.core.compatibility.xmlParse

    // Find all of the *ivy.xml files on the classpath.
    val ivyFiles = new PathMatchingResourcePatternResolver().getResources(
      "classpath*:**/*ivy.xml"
    )
    val streams = ivyFiles.map(_.getInputStream)
    val contents = streams.map(scala.io.Source.fromInputStream).map(_.getLines())
    val nodes = contents.map(c => xmlParse(c.mkString("\n")))

    // Report any errors reading XML
    nodes.flatMap(_.left.toOption).foreach(s => printStream.println(s"Error: $s"))

    // Grab Ivy XML projects
    val projects = nodes.flatMap(_.right.toOption).map(IvyXml.project)

    // Report any errors parsing Ivy XML
    projects.flatMap(_.swap.toOption).foreach(s => printStream.println(s"Error: $s"))

    // Grab dependencies from projects
    val dependencies = projects.flatMap(_.toOption).flatMap(_.dependencies.map(_._2))

    // Return unique dependencies
    dependencies.distinct
  }

  /**
   * Converts the provide repositories to their URI representations.
   *
   * @param repositories The repositories to convert
   * @return The resulting URIs
   */
  private def repositoriesToURIs(repositories: Seq[Repository]) =
    repositories.map {
      case ivy: IvyRepository => ivy.pattern.string
      case maven: MavenRepository => maven.root
    }.map(s => Try(new URI(s))).filter(_.isSuccess).map(_.get)

  /** Creates new Ivy2 local repository using base home URI. */
  private def ivy2Local(ivy2HomeUri: URI) = IvyRepository.parse(
    ivy2HomeUri.toString + "local/" +
      "[organisation]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)" +
      "[revision]/[type]s/[artifact](-[classifier]).[ext]"
  ).toOption.get

  /** Creates new Ivy2 cache repository using base home URI. */
  private def ivy2Cache(ivy2HomeUri: URI) = IvyRepository.parse(
    ivy2HomeUri.toString + "cache/" +
      "(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[organisation]/[module]/" +
      "[type]s/[artifact]-[revision](-[classifier]).[ext]",
    metadataPatternOpt = Some(
      ivy2HomeUri + "cache/" +
        "(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[organisation]/[module]/" +
        "[type]-[revision](-[classifier]).[ext]"
    ),
    withChecksums = false,
    withSignatures = false,
    dropInfoAttributes = true
  ).toOption.get
}


sealed abstract class Credentials extends Product with Serializable {
  def user: String
  def password: String
  def host: String

  def authentication: Authentication =
    Authentication(user, password)
}

object Credentials {

  case class FromFile(file: File) extends Credentials {

    private lazy val props = {
      val p = new Properties()
      p.load(new FileInputStream(file))
      p
    }

    private def findKey(keys: Seq[String]) = keys
      .iterator
      .map(props.getProperty)
      .filter(_ != null)
      .toStream
      .headOption
      .getOrElse {
        throw new NoSuchElementException(s"${keys.head} key in $file")
      }

    lazy val user: String = findKey(FromFile.fileUserKeys)
    lazy val password: String = findKey(FromFile.filePasswordKeys)
    lazy val host: String = findKey(FromFile.fileHostKeys)
  }

  object FromFile {
    // from sbt.Credentials
    private val fileUserKeys = Seq("user", "user.name", "username")
    private val filePasswordKeys = Seq("password", "pwd", "pass", "passwd")
    private val fileHostKeys = Seq("host", "host.name", "hostname", "domain")
  }


  def apply(file: File): Credentials =
    FromFile(file)

}
