import sbt._

import Build._
import Keys._

// This is helper code to validate that generated class files will succed in bytecode verification at class-load time.
object VerifyClassLoad {
  lazy val checkClassLoad: TaskKey[Unit] = TaskKey("check-class-load", "checks whether or not the class files generated by scala are deemed acceptable by classloaders.")
  lazy val checkClassRunner: TaskKey[ClassVerifyRunner] = TaskKey("check-class-runner", "A wrapper around reflective calls to the VerifyClass class.")


  def settings: Seq[Setting[_]] = Seq(
    checkClassRunner <<= (fullClasspath in Runtime) map (cp => new ClassVerifyRunner(data(cp))),
    fullClasspath in checkClassLoad := Seq(),
    checkClassLoad <<= (checkClassRunner, fullClasspath in checkClassLoad, streams) map { (runner, dirs, s) =>
       import collection.JavaConverters._
       val results = runner.run(data(dirs).map(_.getAbsolutePath).toArray).asScala

       s.log.info("Processed " + results.size + " classes.")
       val errors = results.filter(_._2 != null)
       for( (name, result) <- results; if result != null) {
         s.log.error(name + " had error: " + result)
       }
       if(errors.size > 0) error("Classload validation errors encountered")
       ()
    }
  )

  // TODO - Use 
  class ClassVerifyRunner(classpath: Seq[File]) {
    // Classloader that does *not* have this as parent, for differing Scala version.
    lazy val classLoader = new java.net.URLClassLoader(classpath.map(_.toURI.toURL).toArray, null)
    lazy val (mainClass, mainMethod) = try {
      val c = classLoader.loadClass("scala.tools.util.VerifyClass")
      val m = c.getMethod("run", classOf[Array[String]])
      (c,m)
    }
    def run(args: Array[String]): java.util.Map[String,String] = try {
      mainMethod.invoke(null, args).asInstanceOf[java.util.Map[String,String]]
    } catch {
      case e =>
      //error("Could not run Partest: " + e)
      throw e
    }
  }
}
