package li.cil.oc.client.gui

import java.util

import li.cil.oc.Localization
import li.cil.oc.client.gui.widget.ProgressBar
import li.cil.oc.client.{Textures, PacketSender => ClientPacketSender}
import li.cil.oc.common.container.ComponentSlot
import li.cil.oc.common.template.AssemblerTemplates
import li.cil.oc.common.{container, tileentity}
import net.minecraft.client.gui.GuiButton
import net.minecraft.entity.player.InventoryPlayer
import org.lwjgl.opengl.GL11

import scala.collection.convert.WrapAsJava._

class RobotAssembler(playerInventory: InventoryPlayer, val assembler: tileentity.RobotAssembler) extends DynamicGuiContainer(new container.RobotAssembler(playerInventory, assembler)) {
  xSize = 176
  ySize = 192

  private def assemblerContainer = inventorySlots.asInstanceOf[container.RobotAssembler]

  protected var runButton: ImageButton = _

  private val progress = addWidget(new ProgressBar(28, 92))

  def add[T](list: util.List[T], value: Any) = list.add(value.asInstanceOf[T])

  private def validate = AssemblerTemplates.select(assemblerContainer.getSlot(0).getStack).map(_.validate(assemblerContainer.otherInventory))

  private def canBuild = !assemblerContainer.isAssembling && validate.exists(_._1)

  protected override def actionPerformed(button: GuiButton) {
    if (button.id == 0 && canBuild) {
      ClientPacketSender.sendRobotAssemblerStart(assembler)
    }
  }

  override def drawScreen(mouseX: Int, mouseY: Int, dt: Float) {
    runButton.enabled = canBuild
    runButton.toggled = !runButton.enabled
    super.drawScreen(mouseX, mouseY, dt)
  }

  override def initGui() {
    super.initGui()
    runButton = new ImageButton(0, guiLeft + 7, guiTop + 89, 18, 18, Textures.guiButtonRun, canToggle = true)
    add(buttonList, runButton)
  }

  override def drawGuiContainerForegroundLayer(mouseX: Int, mouseY: Int) = {
    GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS) // Me lazy... prevents NEI render glitch.
    if (!assemblerContainer.isAssembling) {
      val info = validate
      val message =
        if (!assemblerContainer.getSlot(0).getHasStack) {
          Localization.Assembler.InsertTemplate
        }
        else info match {
          case Some((_, value, _)) if value != null => value.toString
          case _ if assemblerContainer.getSlot(0).getHasStack => Localization.Assembler.CollectResult
          case _ => ""
        }
      fontRenderer.drawString(message, 30, 94, 0x404040)
      if (runButton.func_82252_a) {
        val tooltip = new java.util.ArrayList[String]
        tooltip.add(Localization.Assembler.Run)
        info.foreach {
          case (valid, _, warnings) => if (valid && warnings.length > 0) {
            tooltip.addAll(warnings.map(_.toString).toList)
          }
        }
        drawHoveringText(tooltip, mouseX - guiLeft, mouseY - guiTop, fontRenderer)
      }
    }
    else if (isPointInRegion(progress.x, progress.y, progress.width, progress.height, mouseX, mouseY)) {
      val tooltip = new java.util.ArrayList[String]
      val timeRemaining = formatTime(assemblerContainer.assemblyRemainingTime)
      tooltip.add(Localization.Assembler.Progress(assemblerContainer.assemblyProgress, timeRemaining))
      copiedDrawHoveringText(tooltip, mouseX - guiLeft, mouseY - guiTop, fontRenderer)
    }
    GL11.glPopAttrib()
  }

  private def formatTime(seconds: Int) = {
    // Assembly times should not / rarely exceed one hour, so this is good enough.
    if (seconds < 60) "0:%02d".format(seconds)
    else "%d:%02d".format(seconds / 60, seconds % 60)
  }

  override def drawGuiContainerBackgroundLayer(dt: Float, mouseX: Int, mouseY: Int) {
    GL11.glColor3f(1, 1, 1) // Required under Linux.
    super.drawGuiContainerBackgroundLayer(dt, mouseX, mouseY)
    mc.renderEngine.bindTexture(Textures.guiRobotAssembler)
    drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize)
    if (assemblerContainer.isAssembling) progress.level = assemblerContainer.assemblyProgress / 100.0
    else progress.level = 0
    drawWidgets()
  }

  override protected def drawDisabledSlot(slot: ComponentSlot) {}

  override def doesGuiPauseGame = false
}