// TLCockpit
// Copyright 2017-2018 Norbert Preining
// Licensed according to GPLv3+
//
// Front end for tlmgr

package TLCockpit

import TLCockpit.ApplicationMain.{stage, tlmgr, tlpkgs}
import TLCockpit.Utils._
import TeXLive.{OsTools, TLPackage}

import scalafx.Includes._
import scalafx.collections.ObservableBuffer
import scalafx.geometry.{HPos, Insets, Orientation}
import scalafx.scene.Cursor
import scalafx.scene.layout.{ColumnConstraints, GridPane, Priority, VBox}
import scalafx.scene.control._
import scalafx.scene.input.MouseEvent
import scalafx.scene.paint.Color

class PkgInfoDialog(tlp: TLPackage) extends Dialog {
  val dialog = new Dialog() {
    initOwner(stage)
    title = s"Package Information for $pkg"
    headerText = s"Package Information for $pkg"
    resizable = true
  }
  dialog.dialogPane().buttonTypes = Seq(ButtonType.OK)
  val isInstalled = tlp.installed
  val grid = new GridPane() {
    hgap = 10
    vgap = 10
    padding = Insets(20)
  }

  def copyableTextfield(k: String): TextField = {
    new TextField() {
      text = k
      editable = false
      style = "-fx-background-color: rgba(0, 0, 0, 0);"
      margin = Insets(0)
      padding = Insets(0)
    }
  }

  def do_one(k: String, v: String, row: Int): Int = {
    grid.add(copyableTextfield(k), 0, row)
    grid.add(copyableTextfield(v), 1, row)
    // grid.add(new Label(k), 0, row)
    // grid.add(new Label(v) {
    //   wrapText = true
    // }, 1, row)
    row + 1
  }

  var crow = 0
  val pkg = tlp.name
  crow = do_one("package", pkg, crow)
  crow = do_one("category", tlp.category, crow)
  crow = do_one("shortdesc", tlp.shortdesc.getOrElse(""), crow)
  crow = do_one("longdesc", tlp.longdesc.getOrElse(""), crow)
  crow = do_one("installed", if (tlp.installed) "Yes" else "No", crow)
  crow = do_one("available", if (tlp.available) "Yes" else "No", crow)
  if (tlp.installed)
    crow = do_one("local revision", tlp.lrev.toString, crow)
  if (tlp.available)
    crow = do_one("remote revision", tlp.rrev.toString, crow)
  val binsizesum = tlp.binsize.values.toList.sum * TeXLive.tlBlockSize
  val binsizestr = if (binsizesum > 0) "bin " + humanReadableByteSize(binsizesum) + " " else ""
  val runsizestr = if (tlp.runsize > 0) "run " + humanReadableByteSize(tlp.runsize) + " " else ""
  val srcsizestr = if (tlp.srcsize > 0) "src " + humanReadableByteSize(tlp.srcsize) + " " else ""
  val docsizestr = if (tlp.docsize > 0) "doc " + humanReadableByteSize(tlp.docsize) + " " else ""
  crow = do_one("sizes", runsizestr + docsizestr + binsizestr + srcsizestr, crow)
  val catdata = tlp.cataloguedata
  if (catdata.version.isDefined)
    crow = do_one("cat-version", catdata.version.get, crow)
  if (catdata.date.isDefined)
    crow = do_one("cat-date", catdata.date.get, crow)
  if (catdata.license.isDefined)
    crow = do_one("cat-license", catdata.license.get, crow)
  if (catdata.topics.isDefined)
    crow = do_one("cat-topics", catdata.topics.get, crow)
  if (catdata.related.isDefined)
    crow = do_one("cat-related", catdata.related.get, crow)
  // add files section
  //println(tlpkgs(pkg))
  val docFiles = tlp.docfiles
  if (docFiles.nonEmpty) {
    // grid.add(new Label("doc files"), 0, crow)
    grid.add(copyableTextfield("doc files"), 0, crow)
    grid.add(doListView(docFiles.map(s => s.file.replaceFirst("RELOC", "texmf-dist")), isInstalled), 1, crow)
    crow += 1
  }
  val runFiles = tlp.runfiles
  if (runFiles.nonEmpty) {
    // grid.add(new Label("run files"), 0, crow)
    grid.add(copyableTextfield("run files"), 0, crow)
    grid.add(doListView(runFiles.map(s => s.replaceFirst("RELOC", "texmf-dist")), false), 1, crow)
    crow += 1
  }
  val srcFiles = tlp.srcfiles
  if (srcFiles.nonEmpty) {
    // grid.add(new Label("src files"), 0, crow)
    grid.add(copyableTextfield("src files"), 0, crow)
    grid.add(doListView(srcFiles.map(s => s.replaceFirst("RELOC", "texmf-dist")), false), 1, crow)
    crow += 1
  }
  val binFiles = tlp.binfiles
  if (binFiles.nonEmpty) {
    // grid.add(new Label("bin files"), 0, crow)
    grid.add(copyableTextfield("bin files"), 0, crow)
    grid.add(doListView(binFiles.flatMap(_._2).toSeq.map(s => s.replaceFirst("RELOC", "texmf-dist")), false), 1, crow)
    crow += 1
  }
  grid.columnConstraints = Seq(new ColumnConstraints(100, 200, 200), new ColumnConstraints(100, 400, 5000, Priority.Always, HPos.LEFT, true))
  dialog.dialogPane().content = grid
  dialog.width = 600
  // dialog.height = 1500
  // dialog

  def showAndWait(): Unit = this.dialog.showAndWait()

  def doListView(files: Seq[String], clickable: Boolean): scalafx.scene.Node = {
    if (files.length <= 5) {
      val vb = new VBox()
      vb.children = files.map { f =>
        val fields = f.split(" ")
        val foo = copyableTextfield(fields(0))
        if (clickable) {
          foo.style = foo.getStyle + "-fx-text-fill: blue;"
          foo.onMouseClicked = { me: MouseEvent => OsTools.openFile(tlmgr.tlroot + "/" + fields(0)) }
          foo.cursor = Cursor.Hand
        }
        foo
        // new Label(fields(0)) {
        //   if (clickable) {
        //     textFill = Color.Blue
        //     onMouseClicked = { me: MouseEvent => OsTools.openFile(tlmgr.tlroot + "/" + fields(0)) }
        //     cursor = Cursor.Hand
        //   }
        // }
      }
      vb
    } else {
      val vb = new ListView[String] {}
      vb.minHeight = 100
      vb.prefHeight = 100
      vb.maxHeight = 200
      vb.vgrow = Priority.Always
      vb.orientation = Orientation.Vertical
      vb.cellFactory = { p => {
        val foo = new ListCell[String]
        // ensure tighter spacing similar to the other entires
        foo.padding = Insets(0)
        foo.item.onChange { (_, _, str) => foo.text = str }
        if (clickable) {
          foo.textFill = Color.Blue
          foo.onMouseClicked = { me: MouseEvent => OsTools.openFile(tlmgr.tlroot + "/" + foo.text.value) }
          foo.cursor = Cursor.Hand
        }
        foo
      }
      }
      // vb.children = docFiles.map { f =>
      vb.items = ObservableBuffer(files.map { f =>
        val fields = f.split(" ")
        fields(0)
      })
      vb
    }
  }

}
