Entity = {class = "Entity"}

function Entity:New(x,y)
	o = {}
	o.pos = {x = x, y = y}
	o.vel = {x = 0, y = 0}

	o.direction = 0

  o.boxCollision = {
		from = {x = x, y = y},
		to = {x = x, y = y},
  }

	o.target_offset = {x = 0, y = 0}

	o.sprite_offset = {x = 0, y = 0}
	o.sprite_scale = {x = 1, y = 1}
	o.sprite_rotation = math.rad(0)
	o.sprite_tint = {1,1,1}
	o.sprite_alpha = 1
	o.sprite_flip = { x = 1, y = 1}
	o.illuminated = false

	setmetatable(o, self)
	self.__index = self

	return o
end

function Entity:CheckNearest(type,maxdistance)
	local return_entity = nil
	local shortest = -1
	for _, entity in pairs(LoadedObjects.Entities) do
		if not type or entity.type == type then
			local distance_x = entity.pos.x - self.pos.x
			local distance_y = entity.pos.y - self.pos.y
			local distance = math.sqrt(distance_x ^ 2 + distance_y ^ 2)

			if not maxdistance or distance < maxdistance then
				if shortest == -1 or distance < shortest then
					shortest = distance
					return_entity = entity
				end
			end

		end
	end
	return return_entity
end

function Entity:Smart()
end

function Entity:Move()
	self.pos.x = self.pos.x + self.vel.x
	self.pos.y = self.pos.y + self.vel.y
end

function Entity:CollisionMove()
	if not self:isCollidingAt(self.pos.x + self.vel.x, self.pos.y, LoadedObjects.Collisions) then
		self.pos.x = self.pos.x + self.vel.x
	else
		self.vel.x = 0
	end
	if not self:isCollidingAt(self.pos.x, self.pos.y + self.vel.y, LoadedObjects.Collisions) then
		self.pos.y = self.pos.y + self.vel.y
	else
		self.vel.y = 0
	end
end

function Entity:LightAdjust(x,y)
	if self.light ~= nil then
		local x = x or 0
		local y = y or 0
		self.light.pos.x = self.pos.x
		self.light.pos.y = self.pos.y
	end
end

function Entity:Kill()
	if self.light ~= nil then
		KillLight(self.light)
	end
	if self.id ~= nil then
		for _, e in pairs(LoadedObjects.Entities) do
			if e.id > self.id then
				e.id = e.id - 1
			end
		end
		table.remove(LoadedObjects.Entities,self.id)
	end
	self = nil
end

function Entity:CheckVisionLine(entity,range)
	local target_x = entity.pos.x + entity.target_offset.x
	local target_y = entity.pos.y + entity.target_offset.y

	local distance_x = target_x - self.pos.x
	local distance_y = target_y - self.pos.y

	local angle = GetAngleFromVector(distance_x,distance_y)
	local distance = math.sqrt(distance_x ^ 2 + distance_y ^ 2)

	local is_colliding = true

	if distance < range then
		is_colliding = false
		for i=1, distance, game.scale do
			if isThereObjectAt(
				self.pos.x+math.cos(angle)*i,
				self.pos.y+math.sin(angle)*i,
				LoadedObjects.Collisions
			) then
				is_colliding = true
			end
		end
	end

	return not is_colliding
end

function Entity:Draw(animation)
	local c1, c2, c3, a = love.graphics.getColor()
	love.graphics.setColor(self.sprite_tint[1],self.sprite_tint[2],self.sprite_tint[3],self.sprite_alpha)
	animation:Draw(
		self.pos.x - Camera.pos.x - ( (self.sprite_offset.x) * math.cos(self.sprite_rotation) - (self.sprite_offset.y) * math.sin(self.sprite_rotation)) * self.sprite_scale.x * self.sprite_flip.x,
		self.pos.y - Camera.pos.y - ( (self.sprite_offset.x) * math.sin(self.sprite_rotation) + (self.sprite_offset.y) * math.cos(self.sprite_rotation)) * self.sprite_scale.y * self.sprite_flip.y,
		self.sprite_rotation,
		self.sprite_scale.x * self.sprite_flip.x,
		self.sprite_scale.y * self.sprite_flip.y
	)
	love.graphics.setColor(c1,c2,c3,a)
end

function Entity:centerOffset(animation,x,y)
	local x = x or 0
	local y = y or 0
	self.sprite_offset.x = animation.imgs[1]:getWidth()/2 + x
	self.sprite_offset.y = animation.imgs[1]:getHeight()/2 + y
end

function Entity:getBoundingBox(animation,top,left,bottom,right)
	local left = left or 0
	local right = right or 0
	local top = top or 0
	local bottom = bottom or 0
	self.boxCollision.from.x = -animation.imgs[1]:getWidth()/2 + left
	self.boxCollision.to.x = animation.imgs[1]:getWidth()/2 + right
	self.boxCollision.from.y = -animation.imgs[1]:getHeight()/2 + top
	self.boxCollision.to.y = animation.imgs[1]:getHeight()/2 + bottom
end

-- returns true if theres a collision at that point. also marks collisioned tile as collision true
function Entity:isCollidingAt(x,y,object)
	for _, collision in pairs(object) do
		if collision.disable then
			-- Dont calculate if disabled
		elseif x + self.boxCollision.from.x < collision.to.x
		and x + self.boxCollision.to.x > collision.from.x
		and y + self.boxCollision.from.y < collision.to.y
		and y + self.boxCollision.to.y > collision.from.y
		then
			collision.isColliding = true
			return true
		end
	end
	return false
end

function Entity:isCollidingWith(entity)
	return self.pos.x + self.boxCollision.from.x < entity.pos.x + entity.boxCollision.to.x
	and entity.pos.x + entity.boxCollision.from.x < self.pos.x + self.boxCollision.to.x
	and	self.pos.y + self.boxCollision.from.y < entity.pos.y + entity.boxCollision.to.y
	and	entity.pos.y + entity.boxCollision.from.y < self.pos.y + self.boxCollision.to.y
end

function Entity:isCollidingAtAll(x,y)
	local result = false
  if not result then
		result = self:isCollidingAt(x,y,objects.collisions)
	end
	if not result then
		result = self:isCollidingAt(x,y,objects.ladders)
 	end
 	if not result then
		result = self:isCollidingAt(x,y,objects.platforms)
	end
 	return result
end

function Entity:CheckVisionLineDebug(entity,range)
	local c1, c2, c3, a = love.graphics.getColor()

	local target_x = entity.pos.x + entity.target_offset.x
	local target_y = entity.pos.y + entity.target_offset.y

	local distance_x = target_x - self.pos.x
	local distance_y = target_y - self.pos.y

	local angle = GetAngleFromVector(distance_x,distance_y)
	local distance = math.sqrt(distance_x ^ 2 + distance_y ^ 2)

	if distance < range then
		for i=1, distance, game.scale do
			if isThereObjectAt(
				self.pos.x+math.cos(angle)*i,
				self.pos.y+math.sin(angle)*i,
				LoadedObjects.Collisions
			) then
				love.graphics.setColor(1,0,0)
			else
				love.graphics.setColor(0,1,0)
			end
			love.graphics.line(
				self.pos.x+math.cos(angle)*i-1 - Camera.pos.x,
				self.pos.y+math.sin(angle)*i-1 - Camera.pos.y,
				self.pos.x+math.cos(angle)*i - Camera.pos.x,
				self.pos.y+math.sin(angle)*i - Camera.pos.y
			)
		end
	end

	love.graphics.setColor(c1,c2,c3,a)
end

function Entity:Debug()
	-- draw center GREEN
	love.graphics.setColor(0,1,0)
	love.graphics.circle("fill", -Camera.pos.x + self.pos.x, -Camera.pos.y + self.pos.y, 1)
	-- draw collision box PURPLE
	love.graphics.setColor(1,0,1)
	love.graphics.rectangle(
		"line",
		-Camera.pos.x + self.pos.x + self.boxCollision.from.x,
		-Camera.pos.y + self.pos.y + self.boxCollision.from.y,
		-Camera.pos.x + self.pos.x + self.boxCollision.to.x -(-Camera.pos.x + self.pos.x + self.boxCollision.from.x),
		-Camera.pos.y + self.pos.y + self.boxCollision.to.y -(-Camera.pos.y + self.pos.y + self.boxCollision.from.y)
	)
	if self.target ~= nil then
		love.graphics.line(
			-Camera.pos.x + self.pos.x,
			-Camera.pos.y + self.pos.y,
			-Camera.pos.x + self.target.x,
			-Camera.pos.y + self.target.y
		)
	end
end
require "code/entities/kupo"
require "code/entities/arrow"
require "code/entities/decoration"
require "code/entities/player"
require "code/entities/fairy"
require "code/entities/cursed_book"
require "code/entities/hook_anchor"
require "code/entities/particle"
