package ocelot.desktop.ui.widget.help

import buildinfo.BuildInfo
import ocelot.desktop.ColorScheme
import ocelot.desktop.geometry.{Padding2D, Size2D}
import ocelot.desktop.graphics.IconSource
import ocelot.desktop.ui.layout.{Layout, LinearLayout}
import ocelot.desktop.ui.widget.{Button, Filler, Icon, Label, PaddingBox, Widget}
import ocelot.desktop.ui.widget.modal.ModalDialog
import ocelot.desktop.util.Orientation.Vertical
import ocelot.desktop.util.{Logging, OcelotOnlineAPI}

import java.awt.Desktop
import java.net.URI
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import scala.collection.immutable.ArraySeq
import scala.util.{Failure, Success}

class UpdateCheckerDialog extends ModalDialog with Logging {
  private val dateFormat = DateTimeFormatter.ofPattern("dd MMM YYYY (HH:mm:ss Z)")

  private val container = new Widget {
    override protected val layout: Layout = new LinearLayout(this, orientation = Vertical)
  }

  children :+= new PaddingBox(
    new Widget {
      override protected val layout: Layout = new LinearLayout(this, orientation = Vertical, gap = 16)

      children :+= container

      children :+= new Widget {
        children :+= new Filler {
          override def maximumSize: Size2D = Size2D(Float.PositiveInfinity, 1)
        }
        children :+= new Button {
          override def text: String = "Ok"
          override def onClick(): Unit = close()
        }
      }
    },
    Padding2D.equal(16),
  )

  // loading screen
  container.children :+= new Label("Checking development news...")

  container.children :+= new PaddingBox(new Icon(IconSource.Loading, color = ColorScheme("Label")),
    Padding2D(16, 0, 0, 90))

  // check the API
  OcelotOnlineAPI.checkRemoteVersion {
    case Success(version) =>
      setContainerChildren(ArraySeq.empty)
      if (version.releaseVersion.isDefined) {
        val newReleaseVersion = version.releaseVersion.get.drop(1)
        container.children :+= new Label(s"Release:      ${BuildInfo.version} ▸ ${newReleaseVersion}")
        if (newReleaseVersion == BuildInfo.version) {
          container.children :+= new PaddingBox(new Label("Up to date!", small = true), Padding2D(6))
        } else {
          container.children :+= new PaddingBox(new Label("New release version is available:", small = true),
            Padding2D(6))
          if (Desktop.isDesktopSupported) {
            container.children :+= new PaddingBox(
              new Button {
                override def text: String = "Download"

                override def onClick(): Unit = Desktop.getDesktop.browse(new URI("https://ocelot.fomalhaut.me/desktop"))
              },
              Padding2D(6),
            )
          } else {
            container.children :+= new PaddingBox(new Label("https://ocelot.fomalhaut.me/desktop", small = true),
              Padding2D(6))
          }
        }
      } else {
        container.children :+= new Label("Release:      N\\A")
      }

      container.children :+= new Filler {
        override def minimumSize: Size2D = Size2D(8, 16)
      }

      if (version.devId.isDefined && version.devDate.isDefined) {
        val newDevVersion = version.devId.get.take(7)
        container.children :+= new Label(s"Dev build:    ${BuildInfo.commit.take(7)} ▸ ${newDevVersion}")
        if (BuildInfo.commit.take(7) == newDevVersion) {
          container.children :+= new PaddingBox(new Label("Up to date!", small = true), Padding2D(6))
        } else {
          container.children :+= new PaddingBox(
            new Label(
              s"New dev build from ${version.devDate.get.withZoneSameInstant(ZoneId.systemDefault()).format(dateFormat)}:",
              small = true,
            ),
            Padding2D(4),
          )
          if (Desktop.isDesktopSupported) {
            container.children :+= new PaddingBox(
              new Button {
                override def text: String = "Download"

                override def onClick(): Unit = Desktop.getDesktop.browse(new URI("https://ocelot.fomalhaut.me/desktop"))
              },
              Padding2D(6),
            )
          } else {
            container.children :+= new PaddingBox(new Label("https://ocelot.fomalhaut.me/desktop", small = true),
              Padding2D(6))
          }
        }
      } else {
        container.children :+= new Label("Dev build:    N\\A")
      }

    case Failure(exception) =>
      logger.error("Cannot download information about new Ocelot version!", exception)
      val message = "Ocelot website is unavailable...\n" +
        s"($exception)\n" +
        "Check the log file for a full stacktrace."
      setContainerChildren(ArraySeq.unsafeWrapArray(message.split('\n').map(line => {
        new Label {
          override def text: String = line
        }
      })))
  }

  private def setContainerChildren(children: ArraySeq[Widget]): Unit = {
    container.children.foreach(it => { it.parent = None; it.root = None })
    container.children = children
  }
}
