package wow.doge.mygame.utils

import java.io.ByteArrayOutputStream
import java.io.OutputStream
import java.io.PrintStream

import scalafx.application.Platform
import scalafx.scene.control.TextArea

trait ConsoleStreamable[T] {
  def println(inst: T, text: String): Unit
  def print(inst: T, text: String): Unit
}

class GenericConsoleStream[T](
    outputStream: OutputStream,
    val config: GenericConsoleStream.Config =
      GenericConsoleStream.Config.default,
    // TODO make this atomic
    private var _streamable: Option[T] = None
)(implicit
    cs: ConsoleStreamable[T]
) extends PrintStream(outputStream, true) {
  private lazy val defaultOut = System.out

  def printToStreamable(stble: Option[T], text: String) =
    stble.foreach(s => cs.println(s, text))

  override def println(text: String): Unit =
    if (config.exclusive) {
      printToStreamable(_streamable, text)
    } else {
      defaultOut.println(text)
      printToStreamable(_streamable, text)
    }

  override def print(text: String): Unit =
    if (config.exclusive) {
      printToStreamable(_streamable, text)
    } else {
      defaultOut.println(text)
      printToStreamable(_streamable, text)
    }

  def :=(s: T) = {
    _streamable match {
      case Some(value) =>
      case None        => _streamable = Some(s)
    }
  }
}

object GenericConsoleStream {

  /**
    * for future use
    */
  case class Config(exclusive: Boolean = false)
  object Config {
    lazy val default = Config()
  }

  implicit val implJFXConsoleStreamForTextArea =
    new ConsoleStreamable[TextArea] {

      override def println(
          ta: TextArea,
          text: String
      ): Unit =
        Platform.runLater(() => ta.appendText(text + "\n"))

      override def print(
          ta: TextArea,
          text: String
      ): Unit =
        Platform.runLater(() => ta.appendText(text))

    }

  def textAreaStream() =
    new GenericConsoleStream[TextArea](
      outputStream = new ByteArrayOutputStream()
    )

}
