package ocelot.desktop.node

import ocelot.desktop.audio._
import ocelot.desktop.graphics.{Graphics, IconSource}
import ocelot.desktop.inventory.SyncedInventory
import ocelot.desktop.node.ComputerAwareNode._
import ocelot.desktop.node.Node.Size
import ocelot.desktop.ui.UiHandler
import ocelot.desktop.ui.event.BrainEvent
import ocelot.desktop.ui.event.handlers.DiskActivityHandler
import ocelot.desktop.ui.particle.Particle
import ocelot.desktop.util.Messages
import ocelot.desktop.{ColorScheme, Settings => DesktopSettings}
import totoro.ocelot.brain.entity.traits.{Entity, Environment, WorkspaceAware}
import totoro.ocelot.brain.event._

import java.util.Calendar

abstract class ComputerAwareNode(entity: Entity with Environment with WorkspaceAware)
  extends EntityNode(entity)
    with SyncedInventory
    with DiskActivityHandler
    with OcelotLogParticleNode
    with BoomCardFxHandler
    with ShiftClickNode {

  eventHandlers += {
    case BrainEvent(event: MachineCrashEvent) =>
      val message = Messages.lift(event.message) match {
        case Some(message) =>
          logger.info(s"[EVENT] Machine crash (address = ${event.address})! Message code ${event.message}: $message")
          message
        case None =>
          logger.info(s"[EVENT] Machine crash (address = ${event.address})! Message: ${event.message}")
          event.message
      }
      UiHandler.root.workspaceView.particleSystem.add(new ErrorMessageParticle(message))

    case BrainEvent(event: BeepEvent) if !Audio.isDisabled =>
      BeepGenerator.newBeep(".", event.frequency, event.duration).play()

    case BrainEvent(event: BeepPatternEvent) if !Audio.isDisabled =>
      BeepGenerator.newBeep(event.pattern, 1000, 200).play()
  }

  protected def drawOverlay(g: Graphics): Unit = HolidayIcon match {
    case Some(icon) if DesktopSettings.get.enableFestiveDecorations =>
      val holidayOverlaySize = Size * 1.6f
      val offset = (holidayOverlaySize - Size) / 2

      g.sprite(
        icon,
        position.x - offset,
        position.y - offset,
        holidayOverlaySize,
        holidayOverlaySize,
      )

    case _ =>
  }

  override def draw(g: Graphics): Unit = {
    super.draw(g)
    drawOverlay(g)
  }

  private class ErrorMessageParticle(message: String) extends Particle(speed = ErrorMessageMoveSpeed) {
    private val offsetX = size.width / 2 - message.length * 4
    private val offsetY = -8
    override def draw(g: Graphics): Unit = {
      g.setSmallFont()
      g.foreground = ColorScheme("ErrorMessage").withAlpha(1 - (2 * time - 1).min(1).max(0))
      g.text(position.x + offsetX, position.y + offsetY - MaxErrorMessageDistance * time, message)
      g.setNormalFont()
    }
  }
}

object ComputerAwareNode {
  private val MaxErrorMessageDistance: Float = 50f
  private val ErrorMessageMoveSpeed: Float = 0.5f

  private val HolidayIcon: Option[IconSource] = {
    var dayOfYear = Calendar.getInstance().get(Calendar.DAY_OF_YEAR)
    val maxDuration = 5

    if (dayOfYear >= 365 - maxDuration) {
      dayOfYear -= 365
    }

    val holidays: Array[(Int, IconSource)] = Array(
      (1, IconSource.Nodes.Holidays.Christmas),
      (45, IconSource.Nodes.Holidays.Valentines),
      (305, IconSource.Nodes.Holidays.Halloween),
    )

    holidays
      .find(holiday => dayOfYear >= holiday._1 - maxDuration && dayOfYear <= holiday._1 + maxDuration)
      .map(holiday => holiday._2)
  }
}
