/*
 * 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.std

import sbt.internal.util.complete
import sbt.internal.util.complete.DefaultParsers
import sbt.{ Def, InputTask, Task }
import sbt.Def.parsed
import sbt.Def.value
import sbt.Def.previous
import sbt.util.CacheImplicits.given

object UseTask:
  val set = Def.setting { 23 }
  val x = Def.task { set.value }
  val y = Def.task { true }
  val z = Def.task { if (y.value) x.value else set.value }
  val a = Def.taskDyn {
    // if y.value then z
    // else x
    if true then z
    else x
  }
end UseTask

object Assign {
  import java.io.File

  import Def.{
    Initialize,
    inputKey,
    // macroValueT, parserToInput,
    settingKey,
    taskKey
  }
  //	import UseTask.{x,y,z,a,set,plain}

  val ak = taskKey[Int]("a")
  val bk = taskKey[Seq[Int]]("b")
  val ck = settingKey[File]("c")
  val intTask = taskKey[Int]("int")
  val sk = taskKey[Set[?]]("s")
  val bgList = taskKey[Seq[Int]]("")

  val ik = inputKey[Int]("i")
  val isk = inputKey[String]("is")
  val mk = settingKey[Int]("m")
  val tk = taskKey[Int]("t")
  val name = settingKey[String]("name")
  val dummyt = taskKey[complete.Parser[String]]("dummyt")
  val dummys = settingKey[complete.Parser[String]]("dummys")
  val dummy3 = settingKey[complete.Parser[(String, Int)]]("dummy3")
  val tsk: complete.Parser[Task[String]] = DefaultParsers.failure("ignored")
  val itsk: Initialize[InputTask[Int]] = inputKey[Int]("ignored")
  val seqSetting = settingKey[Seq[String]]("seqSetting")
  val listSetting = settingKey[List[String]]("listSetting")

  val listTask = taskKey[List[Int]]("listTask")

  /*	def azy = sk.value

  def azy2 = appmacro.Debug.checkWild(Def.task{ sk.value.size })
   */

  val settings = Seq(
    ak :== 1,

    // ak += z.value + (if (y.value) set.value else plain.value),
    ck := new File(ck.value, "asdf"),
    ak := Def.uncached(sk.value.size),
    // bk ++= Seq(z.value)
    intTask := ak.previous.get,
    bgList := { mk.value.toString.toList.map(_.toInt) },
  )

  val sd = Def.settingDyn {
    name
  }

  val zz = Def.task {
    mk.value + tk.value + mk.value + tk.value + mk.value + tk.value + mk.value + tk.value + mk.value + tk.value + mk.value + tk.value
  }

  val dyn: Def.Initialize[Task[Int]] = Def.taskDyn {
    val a = ak.value
    if a < 1 then Def.task { 1 } else Def.task { 0 }
  }

  import DefaultParsers.*
  val p = Def.setting { name.value ~> Space ~> ID }
  val is = Seq(
    mk := 3,
    name := "asdf",
    // name <<= name,
    tk := (math.random() * 1000).toInt,
    // isk := dummys.value.parsed, // should not compile: cannot use a task to define the parser
    // ik := { if (tsk.parsed.value == "blue") tk.value else mk.value }
  )

  val it1 = Def.inputTask {
    //
    tsk.parsed // "as" //dummy.value.parsed
  }
  val it2 = Def.inputTask {
    "lit"
  }

  val it3: Initialize[InputTask[String]] = Def.inputTask[String] {
    itsk.parsed.value.toString
  }

  val it3b: Initialize[InputTask[String]] = Def.inputTask[String] {
    tsk.parsed.value + itsk.parsed.value.toString + isk.evaluated
  }

  // should not compile: cannot use a task to define the parser
  /*	val it4 = Def.inputTask {
  	dummyt.value.parsed
  }*/
  // should compile: can use a setting to define the parser
  val it5 = Def.inputTask {
    dummys.parsed
  }

  val it6a = Def.inputTaskDyn {
    val d3 = dummy3.parsed
    val i = d3._2
    Def.task { tk.value + i }
  }

  val it6b = Def.inputTaskDyn {
    Def.task { 1 }
  }

  val it7 = Def.inputTask {
    it5.parsed
  }

  // def bool: Initialize[Boolean] = Def.setting { true }
  // def enabledOnly[T](key: Initialize[T]): Initialize[Seq[T]] = Def.setting {
  //   val keys: Seq[T] = forallIn(key).value
  //   val enabled: Seq[Boolean] = forallIn(bool).value
  //   (keys zip enabled) collect { case (a, true) => a }
  // }
  // def forallIn[T](key: Initialize[T]): Initialize[Seq[T]] = Def.setting {
  //   key.value :: Nil
  // }

  // // Test that Append.Sequence instances for Seq/List work and don't mess up with each other
  // seqSetting := Seq("test1")
  // seqSetting ++= Seq("test2")
  // seqSetting ++= List("test3")
  // seqSetting += "test4"

  // listSetting := List("test1")
  listSetting ++= List("test2")
  listSetting += "test4"

  listSetting ~= { (xs) => xs }

  listTask := List(1)
  listTask += 1
  listTask += ak.value
}
