/*
 * 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 runtime.actionContainers

import java.net.URI
import java.net.URLClassLoader
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.nio.file.SimpleFileVisitor
import java.nio.file.FileVisitResult
import java.nio.file.FileSystems
import java.nio.file.attribute.BasicFileAttributes
import java.nio.charset.StandardCharsets
import java.util.Base64

import javax.tools.ToolProvider

import collection.JavaConverters._

/**
 * A collection of utility objects to create ephemeral action resources based
 *  on file contents.
 */
object ResourceHelpers {

  /** Creates a zip file based on the contents of a top-level directory. */
  object ZipBuilder {
    def mkBase64Zip(sources: Seq[(Seq[String], String)]): String = {
      val (tmpDir, _) = writeSourcesToTempDirectory(sources)
      val archive = makeZipFromDir(tmpDir)
      readAsBase64(archive)
    }
  }

  /**
   * A convenience object to compile and package Java sources into a JAR, and to
   * encode that JAR as a base 64 string. The compilation options include the
   * current classpath, which is why Google GSON is readily available (though not
   * packaged in the JAR).
   */
  object JarBuilder {
    def mkBase64Jar(sources: Seq[(Seq[String], String)]): String = {
      // Note that this pipeline doesn't delete any of the temporary files.
      val binDir = compile(sources)
      val jarPath = makeJarFromDir(binDir)
      val base64 = readAsBase64(jarPath)
      base64
    }

    def mkBase64Jar(source: (Seq[String], String)): String = {
      mkBase64Jar(Seq(source))
    }

    private def compile(sources: Seq[(Seq[String], String)]): Path = {
      require(!sources.isEmpty)

      // The absolute paths of the source file
      val (srcDir, srcAbsPaths) = writeSourcesToTempDirectory(sources)

      // A temporary directory for the destination files.
      val binDir = Files.createTempDirectory("bin").toAbsolutePath()

      // Preparing the compiler
      val compiler = ToolProvider.getSystemJavaCompiler()
      val fileManager = compiler.getStandardFileManager(null, null, StandardCharsets.UTF_8)

      // Collecting all files to be compiled
      val compUnit = fileManager.getJavaFileObjectsFromFiles(srcAbsPaths.map(_.toFile).asJava)

      // Setting the options
      val compOptions = Seq("-d", binDir.toAbsolutePath().toString(), "-classpath", buildClassPath())
      val compTask = compiler.getTask(null, fileManager, null, compOptions.asJava, null, compUnit)

      // ...and off we go.
      compTask.call()

      binDir
    }

    private def buildClassPath(): String = {
      val bcp = System.getProperty("java.class.path")

      val list = this.getClass().getClassLoader() match {
        case ucl: URLClassLoader =>
          bcp :: ucl.getURLs().map(_.getFile().toString()).toList

        case _ =>
          List(bcp)
      }

      list.mkString(System.getProperty("path.separator"))
    }
  }

  /**
   * Creates a temporary directory and reproduces the desired file structure
   * in it. Returns the path of the temporary directory and the path of each
   * file as represented in it.
   */
  private def writeSourcesToTempDirectory(sources: Seq[(Seq[String], String)]): (Path, Seq[Path]) = {
    // A temporary directory for the source files.
    val srcDir = Files.createTempDirectory("src").toAbsolutePath()

    val srcAbsPaths = for ((sourceName, sourceContent) <- sources) yield {
      // The relative path of the source file
      val srcRelPath = Paths.get(sourceName.head, sourceName.tail: _*)
      // The absolute path of the source file
      val srcAbsPath = srcDir.resolve(srcRelPath)
      // Create parent directories if needed.
      Files.createDirectories(srcAbsPath.getParent)
      // Writing contents
      Files.write(srcAbsPath, sourceContent.getBytes(StandardCharsets.UTF_8))

      srcAbsPath
    }

    (srcDir, srcAbsPaths)
  }

  private def makeZipFromDir(dir: Path): Path = makeArchiveFromDir(dir, ".zip")

  private def makeJarFromDir(dir: Path): Path = makeArchiveFromDir(dir, ".jar")

  /**
   * Compresses all files beyond a directory into a zip file.
   * Note that Jar files are just zip files.
   */
  private def makeArchiveFromDir(dir: Path, extension: String): Path = {
    // Any temporary file name for the archive.
    val arPath = Files.createTempFile("output", extension).toAbsolutePath()

    // We "mount" it as a filesystem, so we can just copy files into it.
    val dstUri = new URI("jar:" + arPath.toUri().getScheme(), arPath.toAbsolutePath().toString(), null)
    // OK, that's a hack. Doing this because newFileSystem wants to create that file.
    arPath.toFile().delete()
    val fs = FileSystems.newFileSystem(dstUri, Map(("create" -> "true")).asJava)

    // Traversing all files in the bin directory...
    Files.walkFileTree(
      dir,
      new SimpleFileVisitor[Path]() {
        override def visitFile(path: Path, attributes: BasicFileAttributes) = {
          // The path relative to the src dir
          val relPath = dir.relativize(path)

          // The corresponding path in the zip
          val arRelPath = fs.getPath(relPath.toString())

          // If this file is not top-level in the src dir...
          if (relPath.getParent() != null) {
            // ...create the directory structure if it doesn't exist.
            if (!Files.exists(arRelPath.getParent())) {
              Files.createDirectories(arRelPath.getParent())
            }
          }

          // Finally we can copy that file.
          Files.copy(path, arRelPath)

          FileVisitResult.CONTINUE
        }
      })

    fs.close()

    arPath
  }

  /** Reads the contents of a (possibly binary) file into a base64-encoded String */
  def readAsBase64(path: Path): String = {
    val encoder = Base64.getEncoder()
    new String(encoder.encode(Files.readAllBytes(path)), StandardCharsets.UTF_8)
  }
}
