local function move_towards_center() end
local function move_towards_crush_point() end
local function rotate_randomly() end
local function set_crush_point() end
local function go_towards() end

local T = fbrawl.T
fbrawl.cry_of_gaia_area_particle_spawner = {
	amount = 1800,
	radius = 12,
	time = 2,
	minsize = 8,
	maxsize = 9,
	glow = 12,
	texture = {
		 name = "fbrawl_fire_particle.png",
		 alpha_tween = {1, 0},
		 scale_tween = {
			  {x = 1, y = 1},
			  {x = 0, y = 0},
		 },
		 animation = {
			  type = "vertical_frames",
			  aspect_w = 16, aspect_h = 16,
			  length = 0.1,
		 },
	},
	minexptime = 0.3,
	maxexptime = 0.3,
}



skills.register_skill("fbrawl:cry_of_gaia", {
   name = T("Cry of Gaia"),
	description = T("Unleash Gaia's fury: throws a meteor shower wherever you're looking at, damaging all enemies in that area."),
	icon = "fbrawl_cry_of_gaia_skill.png",
   slot = 4,
	range = 200,
   sounds = {
      cast = {name = "fbrawl_meteor_rising", max_hear_distance = 46}
   },
	get_meteor_center = function(self)
		local look_dir = self.player:get_look_dir()
		local offset = {x = look_dir.x*7, y = 14, z = look_dir.z*7}
		self.data.meteor_center = self.data.meteor_center or vector.add(offset, self.player:get_pos())

		return self.data.meteor_center
	end,
   cast = function(self)
		local meteors = {
			{x=6, y=-2, z=0},
			{x=-6, y=-2, z=0},
			{x=0, y=-2, z=-6},
			{x=0, y=-2, z=6},
			{x=0, y=-2, z=-6},
			{x=6, y=-2, z=6},
			{x=-6, y=-2, z=-6}
		}
		self.data.meteor_center = nil

		for _, pos in ipairs(meteors) do
			minetest.add_entity(vector.add(pos, self.player:get_pos()), "fantasy_brawl:meteor", self.pl_name)
		end
   end
})



-- The meteor entity declaration.
local tex = "fbrawl_meteor_entity.png"
local meteor = {
   initial_properties = {
      hp_max = 999,
      physical = false,
      collide_with_objects = false,
      visual = "cube",
      visual_size = {x = 1.9, y = 1.9},
      textures = {tex,tex,tex,tex,tex,tex},
		automatic_face_movement_dir = false,
      range = 12,
      damage = 10
   },
	_speed = 20,
   _pl_name = "",
	_positioned = false,
	_crush_point = {},
	_time_passed = 0,
	_fall_speed_multiplier = 5
}



-- staticdata = player's username.
function meteor:on_activate(staticdata, dtime_s)
   local obj = self.object

   if staticdata then
      self._pl_name = staticdata
      local player = minetest.get_player_by_name(self._pl_name)
		local skill = self._pl_name:get_skill("fbrawl:cry_of_gaia")

      if not player then
         obj:remove()
         return
      end

		if not set_crush_point(self) then return end

		go_towards(self, skill:get_meteor_center(), self._speed)

		--fbrawl.camera_shake(self._pl_name, 20, 0.4)
   else
      obj:remove()
      return
   end

   minetest.add_particlespawner({
		amount = 320,
		time = 0,
		minpos = {x = -2, y = 2, z = -2},
		maxpos = {x = 2, y = -2, z = 2},
		minvel = {x = 0, y = -0.2, z = 0},
		maxvel = {x = 0, y = 0.2, z = 0},
		minsize = 4,
		maxsize = 9,
		glow = 12,
		texture = {
			 name = "fbrawl_fire_particle.png",
			 alpha_tween = {1, 0},
			 scale_tween = {
				  {x = 1, y = 1},
				  {x = 0, y = 0},
			 },
			 animation = {
				  type = "vertical_frames",
				  aspect_w = 16, aspect_h = 16,
				  length = 0.3,
			 },
		},
		minexptime = 1.5,
		maxexptime = 2,
		attached = obj
  })
end



function meteor:crush()
   local sound = {name = "fbrawl_meteor_hit", pos = self.object:get_pos(), max_hear_distance = 46}
   local player = minetest.get_player_by_name(self._pl_name)
   local props = self.initial_properties

   minetest.sound_play(sound, sound, true)

	minetest.add_particlespawner({
		amount = 300,
		time = 0.5,
		pos = {
			min = vector.add(self.object:get_pos(), -2),
			max = vector.add(self.object:get_pos(), 2),
		},
		minvel = {x = -10,y = -6, z = -10},
		maxvel = {x = 10, y = 6, z = 10},
		minsize = 10,
		maxsize = 16,
		texture = {
			name = "fbrawl_fire_particle.png",
			alpha_tween = {1, 0},
			scale_tween = {
				 {x = 1, y = 1},
				 {x = 0, y = 0},
			},
			animation = {
				 type = "vertical_frames",
				 aspect_w = 16, aspect_h = 16,
				 length = 0.3,
			},
	  	},
		glow = 12,
		minexptime = 2,
		maxexptime = 3,
	})

	fbrawl.damage_players_near(player, self.object:get_pos(), props.range, props.damage)
	fbrawl.camera_shake(self._pl_name, 6, 0.4)

   self.object:remove()
end



function meteor:on_step(dtime)
   local player = minetest.get_player_by_name(self._pl_name)

	if not player then
      self.object:remove()
      return
   end

	if not self._positioned then
		move_towards_center(self)
	else
		local is_arrived = move_towards_crush_point(self, dtime)

		if is_arrived or fbrawl.are_there_nodes_in_area(self.object:get_pos(), 1) then 		
			self:crush()
			return
		end
	end

	rotate_randomly(self, dtime)
end



minetest.register_entity("fantasy_brawl:meteor", meteor)



function move_towards_center(meteor) 
	local skill = meteor._pl_name:get_skill("fbrawl:cry_of_gaia")
	local obj = meteor.object

	local is_positioned = vector.distance(obj:get_pos(), skill:get_meteor_center()) <= 2

	if is_positioned then
		obj:set_velocity({x = 0, y = 0, z = 0})
		meteor._positioned = true

		local sound = {name = "fbrawl_meteor_thrown", pos = obj:get_pos(), max_hear_distance = 46}
		minetest.sound_play(sound, sound, true)
	else
		go_towards(meteor, skill:get_meteor_center(), meteor._speed)
	end
end



function move_towards_crush_point(meteor, dtime)
	local obj = meteor.object
	local distance = vector.distance(obj:get_pos(), meteor._crush_point)
	local is_arrived = distance <= 0.8

	if not is_arrived then
		meteor._time_passed = meteor._time_passed + dtime
		if meteor._time_passed < 0.5 then return end

		if distance <= 2 then
			meteor._fall_speed_multiplier = 0.5
		end
		
		go_towards(meteor, meteor._crush_point, meteor._speed * meteor._fall_speed_multiplier)
	else
		return "is_arrived"
	end
end



function rotate_randomly(meteor, dtime)
	local random_speed = PseudoRandom(minetest.get_us_time()):next(10, 15) / 10
	meteor._rot_speed = meteor._rot_speed or random_speed * dtime

	meteor.object:set_rotation(vector.add(meteor.object:get_rotation(), meteor._rot_speed))
end



function set_crush_point(meteor)
	local player = minetest.get_player_by_name(meteor._pl_name)
	local pl_pos = vector.add(player:get_pos(), {x=0, y=1, z=0})
	
	local ray = fbrawl.look_raycast(player, 200)
	local crush_point = ray:next() or {}
	meteor._crush_point = crush_point.above

	if not meteor._crush_point then
		meteor.object:remove()
		return false
	end

	return true
end



function go_towards(meteor, pos, speed)
	local dir = vector.direction(meteor.object:get_pos(), pos)

	meteor.object:set_velocity({
		x=(dir.x * speed),
		y=(dir.y * speed),
		z=(dir.z * speed),
	})
end