package ocelot.desktop.ui.particle

import ocelot.desktop.graphics.Graphics
import ocelot.desktop.ui.widget.Widget

import scala.collection.mutable
import scala.collection.mutable.ListBuffer
import scala.reflect.{ClassTag, classTag}

class ParticleSystem {
  private val particles: ListBuffer[Particle] = ListBuffer.empty
  private val counts = mutable.HashMap.empty[(Class[_], Option[Widget]), Int]

  def add(particle: Particle): Unit = {
    particles += particle
    updateCount(particle, 1)
  }

  def count[A : ClassTag](origin: Option[Widget]): Int = counts.getOrElse((classTag[A].runtimeClass, origin), 0)

  /**
    * Calls `update` method on all particles, advances time.
    * Removes expired particles.
    * @param dt  delta time
    */
  def update(dt: Float): Unit = {
    particles.filterInPlace { particle =>
      particle.update(dt)
      val expired = particle.expired

      if (expired) {
        updateCount(particle, -1)
      }

      !expired
    }
  }

  def draw(g: Graphics): Unit = {
    particles.foreach(_.draw(g))
  }

  def clear(): Unit = {
    particles.clear()
  }

  private def updateCount(particle: Particle, delta: Int): Unit = {
    counts.updateWith((particle.getClass, particle.origin)) { v =>
      val newValue = v.getOrElse(0) + delta

      Option.when(newValue > 0)(newValue)
    }
  }
}
