/*
 * 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.io.ByteArrayOutputStream
import java.io.File
import java.io.PrintWriter

import scala.concurrent.Await
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.concurrent.blocking
import scala.concurrent.duration.Duration
import scala.concurrent.duration.DurationInt
import scala.language.postfixOps
import scala.sys.process.ProcessLogger
import scala.sys.process.stringToProcess
import scala.util.Random

import org.apache.commons.lang3.StringUtils
import org.scalatest.FlatSpec
import org.scalatest.Matchers

import akka.actor.ActorSystem
import common.WhiskProperties
import spray.json._
import whisk.core.entity.Exec

/**
 * For testing convenience, this interface abstracts away the REST calls to a
 * container as blocking method calls of this interface.
 */
trait ActionContainer {
  def init(value: JsValue): (Int, Option[JsObject])
  def run(value: JsValue): (Int, Option[JsObject])
}

trait ActionProxyContainerTestUtils extends FlatSpec with Matchers {
  import ActionContainer.{filterSentinel, sentinel}

  def initPayload(code: String, main: String = "main") = {
    JsObject(
      "value" -> JsObject(
        "code" -> { if (code != null) JsString(code) else JsNull },
        "main" -> JsString(main),
        "binary" -> JsBoolean(Exec.isBinaryCode(code))))
  }

  def runPayload(args: JsValue, other: Option[JsObject] = None) = {
    JsObject(Map("value" -> args) ++ (other map { _.fields } getOrElse Map()))
  }

  def checkStreams(out: String, err: String, additionalCheck: (String, String) => Unit, sentinelCount: Int = 1) = {
    withClue("expected number of stdout sentinels") {
      sentinelCount shouldBe StringUtils.countMatches(out, sentinel)
    }
    withClue("expected number of stderr sentinels") {
      sentinelCount shouldBe StringUtils.countMatches(err, sentinel)
    }

    val (o, e) = (filterSentinel(out), filterSentinel(err))
    o should not include (sentinel)
    e should not include (sentinel)
    additionalCheck(o, e)
  }
}

object ActionContainer {
  private lazy val dockerBin: String = {
    List("/usr/bin/docker", "/usr/local/bin/docker")
      .find { bin =>
        new File(bin).isFile()
      }
      .getOrElse(???) // This fails if the docker binary couldn't be located.
  }

  private lazy val dockerCmd: String = {
    val version = WhiskProperties.getProperty("whisk.version.name")
    // Check if we are running on docker-machine env.
    val hostStr = if (version.toLowerCase().contains("mac")) {
      s" --host tcp://${WhiskProperties.getMainDockerEndpoint()} "
    } else {
      " "
    }
    s"$dockerBin $hostStr"
  }

  private def docker(command: String): String = s"$dockerCmd $command"

  // Runs a process asynchronously. Returns a future with (exitCode,stdout,stderr)
  private def proc(cmd: String): Future[(Int, String, String)] = Future {
    blocking {
      val out = new ByteArrayOutputStream
      val err = new ByteArrayOutputStream
      val outW = new PrintWriter(out)
      val errW = new PrintWriter(err)
      val v = cmd ! (ProcessLogger(outW.println, errW.println))
      outW.close()
      errW.close()
      (v, out.toString, err.toString)
    }
  }

  // Tying it all together, we have a method that runs docker, waits for
  // completion for some time then returns the exit code, the output stream
  // and the error stream.
  private def awaitDocker(cmd: String, t: Duration): (Int, String, String) = {
    Await.result(proc(docker(cmd)), t)
  }

  // Filters out the sentinel markers inserted by the container (see relevant private code in Invoker.scala)
  val sentinel = "XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX"
  def filterSentinel(str: String) = str.replaceAll(sentinel, "").trim

  def withContainer(imageName: String, environment: Map[String, String] = Map.empty)(code: ActionContainer => Unit)(
    implicit actorSystem: ActorSystem): (String, String) = {
    val rand = { val r = Random.nextInt; if (r < 0) -r else r }
    val name = imageName.toLowerCase.replaceAll("""[^a-z]""", "") + rand
    val envArgs = environment.toSeq.map {
      case (k, v) => s"-e ${k}=${v}"
    } mkString (" ")

    // We create the container...
    val runOut = awaitDocker(s"run --name $name $envArgs -d $imageName", 10 seconds)
    assert(runOut._1 == 0, "'docker run' did not exit with 0: " + runOut)

    // ...find out its IP address...
    val ipOut = awaitDocker(s"""inspect --format '{{.NetworkSettings.IPAddress}}' $name""", 10 seconds)
    assert(ipOut._1 == 0, "'docker inspect did not exit with 0")
    val ip = ipOut._2.replaceAll("""[^0-9.]""", "")

    // ...we create an instance of the mock container interface...
    val mock = new ActionContainer {
      def init(value: JsValue) = syncPost(ip, 8080, "/init", value)
      def run(value: JsValue) = syncPost(ip, 8080, "/run", value)
    }

    try {
      // ...and finally run the code with it.
      code(mock)
      // I'm told this is good for the logs.
      Thread.sleep(100)
      val (_, out, err) = awaitDocker(s"logs $name", 10 seconds)
      (out, err)
    } finally {
      awaitDocker(s"kill $name", 10 seconds)
      awaitDocker(s"rm $name", 10 seconds)
    }
  }

  private def syncPost(host: String, port: Int, endPoint: String, content: JsValue): (Int, Option[JsObject]) = {
    whisk.core.containerpool.HttpUtils.post(host, port, endPoint, content)
  }

  private class ActionContainerImpl() extends ActionContainer {
    override def init(value: JsValue) = ???
    override def run(value: JsValue) = ???
  }
}
