local MoveSystem = inherited("MoveSystem", SystemMap)

function MoveSystem:new()
	local ms = instance(self)
	return ms
end

function MoveSystem:wants(ent)
	return ent.aspects.movement
end

function MoveSystem:ent_added(ent)
end

function MoveSystem:ent_removed(ent)
end

function MoveSystem:step(dt)
	local world = self.world
	local universe = world.universe
	local TILES = TILES
	for ent, _ in pairs(self.ents) do
		local nx = ent.nx
		local ny = ent.ny
		local nz = ent.nz

		local dx = ent.dx
		local dy = ent.dy
		local dz = ent.dz

		local col,row = universe:position_to_col_row(nx,ny)
		local blocking = universe:is_tile_blocking_at_col_row(col,row)
		if blocking then
			--calc normal
			local x = ent.x
			local y = ent.y

			local xcol,xrow = universe:position_to_col_row(nx,y)
			local ycol,yrow = universe:position_to_col_row(x,ny)
			
			local dx_blocking = universe:is_tile_blocking_at_col_row(xcol,xrow)
			local dy_blocking = universe:is_tile_blocking_at_col_row(ycol,yrow)
			
			ent.any_impact = true

			if dx_blocking then
				dx = -dx*ent.bounciness
				ent.dx_impact = dx-ent.dx
				ent.dx = dx
				col = xcol
				nx = x
			end

			if dy_blocking then
				dy = -dy*ent.bounciness
				ent.dy_impact = dy-ent.dy
				ent.dy = dy
				row = yrow
				ny = y
			end			
		elseif ent.any_impact then
			ent.any_impact = false
			ent.dx_impact = nil
			ent.dy_impact = nil
		end

		if nz < 0 then
			nz = 0
			if dz ~= 0 then
				dz = math.approach(math.abs(dz)*ent.bounciness_z, 0, (1-ent.bounciness_z))
				ent.dz = dz
			end
		else
			dz = dz - dt*ent.gravity
			ent.dz = dz
		end

		ent.x = nx
		ent.y = ny
		ent.z = nz
		ent.nx = ent.x + dx*dt
		ent.ny = ent.y + dy*dt
		ent.nz = ent.z + dz*dt

		if col ~= ent.col or row ~= ent.row then
			ent:next_col_row(col, row)
			ent.col = col
			ent.row = row
		end
		
		local cur_chunk = ent.chunk
		if cur_chunk then

			local chunk = universe:get_chunk_at_col_row(col,row)
			if cur_chunk ~= chunk then
				world:move_ent_to_chunk(ent, chunk)				
			end
		end
	end
end

return MoveSystem