export class GameObject {
  x = 0
  y = 0
  sizeX = 0
  sizeY = 0
  heightX = 0
  heightY = 0
  speed = 0
  angle = 0
  health = 0
  isAnimated = false
  removeAfterAnimation = false
  animationRunning = false
  frames = 0
  framesCounter = 0

  get sprite() {
    return this.spriteImg
  }

  step(tickToSimulate) {
    for (let i = 0; i < tickToSimulate; i++) {
      this.x = this.x + this.speed * Math.cos(this.angle)
      this.y = this.y + this.speed * Math.sin(this.angle)
    }

    // Improve canvas performances
    this.x = Math.floor(this.x)
    this.y = Math.floor(this.y)
  }

  // Crude collision box
  collideWith(gameObject, customSizeX, customSizeY) {
    const sizeX = customSizeX ? customSizeX : this.sizeX
    const sizeY = customSizeY ? customSizeY : this.sizeY

    const x = this.x - sizeX
    const y = this.y - sizeY
    const a = x + sizeX * 2
    const b = y + sizeY * 2

    const x1 = gameObject.x - gameObject.sizeX
    const y1 = gameObject.y - gameObject.sizeY
    const a1 = x1 + gameObject.sizeX * 2
    const b1 = y1 + gameObject.sizeY * 2

    return !(a < x1 || a1 < x || b < y1 || b1 < y)
  }
}

export class Meteor extends GameObject {
  constructor(maxX, maxY, maxHealth, meteorSprite, meteorSpriteList) {
    super()
    const xOrigin = Math.floor(Math.random() * maxX - 10) + 10
    const xTarget = Math.floor(Math.random() * maxX - 20) + 20

    const dx = xTarget - xOrigin
    const dy = maxY

    this.angle = Math.atan2(dy, dx)
    this.speed = Math.floor(Math.random() * 0.5) + 0.1
    this.health = Math.floor(Math.random() * (maxHealth - 1)) + 1

    this.x = xOrigin
    this.y = 0
    this.sizeX = 25
    this.sizeY = 25
    this.heightX = 256
    this.heightY = 256
    this.meteorSprite = meteorSprite
    this.meteorSpriteList = meteorSpriteList
    this.isAnimated = false
    this.removeAfterAnimation = false
    this.animationRunning = false
    this.frames = 4
    this.framesCounter = 0
  }

  get sprite() {
    if (this.meteorSprite) {
      return this.meteorSprite
    } else if (this.health <= 10) {
      return this.meteorSpriteList[0]
    } else if (this.health <= 20) {
      return this.meteorSpriteList[1]
    } else if (this.health <= 30) {
      return this.meteorSpriteList[2]
    } else {
      return this.meteorSpriteList[3]
    }
  }
}

export class Bullet extends GameObject {
  constructor(x, y, angle, bulletSprite, damage, aoe, aoeSize, percing, health) {
    super()
    this.x = x
    this.y = y
    this.sizeX = 5
    this.sizeY = 10
    this.heightX = 0
    this.heightY = 0
    this.spriteImg= bulletSprite
    this.speed = 1
    this.angle = angle
    this.health = health
    this.damage = damage
    this.percing = percing
    this.aoe = aoe
    this.aoeSize = aoeSize
    this.isAnimated = false
    this.removeAfterAnimation = false
    this.animationRunning = false
    this.frames = 0
    this.framesCounter = 0
  }
}

export class Explosion extends GameObject {
  constructor(x, y, explosionSprite, size = 30) {
    super()
    this.x = x
    this.y = y
    this.sizeX = size
    this.sizeY = size
    this.heightX = 128
    this.heightY = 128
    this.spriteImg= explosionSprite
    this.isAnimated = true
    this.removeAfterAnimation = true
    this.animationRunning = true
    this.frames = 32
    this.framesCounter = 0
  }
}

export class Turret extends GameObject {
  constructor(x, y) {
    super()
    this.x = x
    this.y = y
    this.sizeX = 25
    this.sizeY = 35
    this.heightX = 0
    this.heightY = 0
    this.spriteImg= null
    this.bulletSprite = null
    this.isAnimated = false
    this.removeAfterAnimation = false
    this.animationRunning = false
    this.frames = 0
    this.framesCounter = 0
    this.firingRate = 0
    this.spread = 0
    this.damage = 0
  }
}