
-- because math.floor is slow
local floor = function(n)
  return (n - n % 1)
end


class('Fish').extends(playdate.graphics.sprite)

function Fish:init()

	Fish.super.init(self)

	-- image table is 7 wide by 3 tall, each cell is 48x48 pixels
	-- self.swimImages = playdate.graphics.imagetable.new('Fish/fish')
	self.swimImages = playdate.graphics.imagetable.new('Fish/fish')

	self:setCollideRect(0, 0, 48, 48)
	self:setZIndex(800)

	self.kFishNormalState = 1
	self.kFishHoverState = 2

	self:reset()
	self:addSprite()
end


function Fish:reset()
	self.xd = 0
	self.yd = 0
	self.v = 0
	self.justSwam = 0	-- this is just a janky way to handle a two-frame angle animation change when a swim occurs

	self.frame = 0
	self:updateFrame()

	self:moveTo(playdate.display.getWidth() / 4, playdate.display.getHeight() / 4)

	-- state stuff for the hover state
	self.fishState = self.kFishHoverState
	self.hoverTime = 0
	self.hoverY = self.y
	self.wasHovering = true		-- messy and hacky
end



function Fish:up()

	self.wasHovering = false

	if self.fishState == self.kFishNormalState then
		if self.v > 160 then
			self.justSwam = 2
		elseif self.v > 100 then
			self.justSwam = 1
		end

		self.v = -160
	end
end


function Fish:left()
	if self.fishState == self.kFishNormalState then
		self.xd = -8
	end
end


function Fish:right()
	if self.fishState == self.kFishNormalState then
		self.xd = 8
	end
end


function Fish:updateFrame()

	-- figure out what angle we should be using based on our verical velocity
	-- fishAngle goes from 1 to 7, with 3 being completely horizontal
	-- self.frame itself ranges from 0 to 7, while actualFrame oscillates between 0 and 2

	local fishAngle = 3

	if self.fishState == self.kFishNormalState then

		if self.justSwam == 2 then
			fishAngle = 5
			self.justSwam = 1
		elseif self.justSwam == 1 then
			fishAngle = 3
			self.justSwam = 0
		else

			if self.v < 60 and self.wasHovering == false then
				fishAngle = 1
			elseif self.v < 90 and self.wasHovering == false then
				fishAngle = 2
			elseif self.v > 280 then
				fishAngle = 7
			elseif self.v > 240 then
				fishAngle = 6
			elseif self.v > 200 then
				fishAngle = 5
			elseif self.v > 150 then
				fishAngle = 4

			if self.v > 90 then
				self.wasHovering = false
			end

			end
		end
	end

	self.frame = (self.frame + 1) % 8
	local actualFrame = floor(self.frame / 2)
	if actualFrame == 3 then
		actualFrame = 1
	end

	-- stop swimming if we're nose-diving
	if self.v > 240 then
		actualFrame = 1
	end

	local tableWidth = 7
	self:setImage(self.swimImages[fishAngle + tableWidth * actualFrame])

end


function Fish:update()

	if self.fishState == self.kFishHoverState then
		self:updateHover()
	else
		self:updateNormal()
	end
end


function Fish:updateNormal()

	local a = 440 -- pixels per second^2
	local dt = 1.0/20

	self:updateFrame()

	self.v = self.v + a * dt
	if self.v > 400 then	-- terminal fish velocity
		self.v = 400
	end

	local distance = self.v * dt

	-- collision response logic for the fish instance (flippy) is handled in main.lua in `function flippy:collisionResponse(other)`
	self:moveWithCollisions(self.x + self.xd, self.y + distance)

	-- decelerate any x movement
	if (self.xd > 0.5 or self.xd < -0.5) then
		self.xd = self.xd * 0.8
	else
		self.xd = 0.0
	end
end


function Fish:updateHover()
	self:updateFrame()

	local dt = 1/20
	self.hoverTime = self.hoverTime + dt
	local occilationsPerSecond = 2.6
	local amplitude = 3.5
	local y = math.sin(math.pi * self.hoverTime * occilationsPerSecond) * amplitude
	self:moveTo(self.x, self.hoverY + y)
end
