package edu.colorado.phet.movingman.ladybug

import scala.collection.mutable.ArrayBuffer

trait ObservableS {
  private val listeners = new ArrayBuffer[() => Unit]

  def notifyListeners(): Unit = listeners.foreach(_())

  def addListener(listener: () => Unit) = listeners += listener
}

class Observable[T] {
  private val listeners = new ArrayBuffer[T => Unit]

  def notifyListeners(obj: T): Unit = listeners.foreach(_(obj))

  def addListener(listener: T => Unit) = listeners += listener
}

case class LadybugState(_position: Vector2D, _velocity: Vector2D, _acceleration: Vector2D, _angle: Double) {
  val position = _position
  val velocity = _velocity
  val acceleration = _acceleration
  val angle = _angle

  def this() = this (new Vector2D, new Vector2D, new Vector2D, 0)

  def this(copy: LadybugState) = this (copy.position, copy.velocity, copy.acceleration, copy.angle)

  def translate(dx: Double, dy: Double): LadybugState = new LadybugState(new Vector2D(position.x + dx, position.y + dy),
    velocity, acceleration, angle)

  def rotate(dtheta: Double): LadybugState = new LadybugState(position, velocity, acceleration, angle + dtheta)

  def setAngle(theta: Double): LadybugState = new LadybugState(position, velocity, acceleration, theta)

  def setVelocity(v: Vector2D): LadybugState = new LadybugState(position, v, acceleration, angle)

  def setAcceleration(a: Vector2D): LadybugState = new LadybugState(position, velocity, a, angle)

  def setPosition(x: Vector2D): LadybugState = new LadybugState(x, velocity, acceleration, angle)
}

class Ladybug extends Observable[Ladybug] {
  var state = new LadybugState

  def resetAll() = {
    state = new LadybugState
    notifyListeners(this)
  }

  def translate(deltaPosition: Vector2D): Unit = translate(deltaPosition.x, deltaPosition.y)

  def translate(dx: Double, dy: Double) = {
    state = state.translate(dx, dy);
    notifyListeners(this)
  }

  def rotate(dtheta: Double) = setAngle(getAngle + dtheta)

  def getPosition: Vector2D = state.position

  def getAngle: Double = state.angle

  def getState = state

  def getVelocity = state.velocity

  def getAcceleration = state.acceleration

  def setAcceleration(acceleration: Vector2D) = {
    state = state.setAcceleration(acceleration)
    notifyListeners(this)
  }

  def setPosition(position: Vector2D) = {
    state = state.setPosition(position)
    notifyListeners(this)
  }

  def setVelocity(velocity: Vector2D) = {
    state = state.setVelocity(velocity)
    notifyListeners(this)
  }

  def setAngle(theta: Double) = {
    state = state.setAngle(theta)
    notifyListeners(this)
  }

  def setState(_state: LadybugState) = {
    state = _state
    notifyListeners(this)
  }

}