/*
 * sbt
 * Copyright 2023, Scala center
 * Copyright 2011 - 2022, Lightbend, Inc.
 * Copyright 2008 - 2010, Mark Harrah
 * Licensed under Apache License 2.0 (see LICENSE)
 */

package sbt

import java.io.File
import sbt.internal.util.Relation

import sbt.io.IO

object DotGraph {
  def generateGraph[K, V](
      file: File,
      graphName: String,
      relation: Relation[K, V],
      keyToString: K => String,
      valueToString: V => String
  ): Unit = {
    import scala.collection.mutable.{ HashMap, HashSet }
    val mappedGraph = new HashMap[String, HashSet[String]]
    for ((key, values) <- relation.forwardMap; keyString = keyToString(key); value <- values)
      mappedGraph.getOrElseUpdate(keyString, new HashSet[String]) += valueToString(value)

    val mappings =
      for {
        (dependsOn, dependents) <- mappedGraph.toSeq
        dependent <- dependents
        if dependent != dependsOn && !dependsOn.isEmpty && !dependent.isEmpty
      } yield "\"" + dependent + "\" -> \"" + dependsOn + "\""

    val lines =
      ("digraph " + graphName + " {") +:
        mappings :+
        "}"

    IO.writeLines(file, lines)
  }
  def sourceToString(roots: Iterable[File], source: File) =
    relativized(roots, source).trim.stripSuffix(".scala").stripSuffix(".java")

  private def relativized(roots: Iterable[File], path: File): String = {
    val relativized = roots.flatMap(root => IO.relativize(root, path))
    val shortest = relativized.foldLeft(Int.MaxValue)(_ min _.length)
    relativized.find(_.length == shortest).getOrElse(path.getName)
  }
}
