-- squadai util file

function assert_isnum( arg, message )
	
	if (type(arg) ~= "number") then
		
		error( "squadai: assert_isnum. got "..type(arg).." instead. Value:"..tostring(arg).." "..message, 3 )
	end

end

function assert_isbool( arg, message )
	
	if (type(arg) ~= "boolean") then
		error( "squadai: assert_isbool. got "..type(arg).." instead. Value:"..tostring(arg).." "..message, 3 )
	end

end

function assert_isstr( arg, message )
	
	if (type(arg) ~= "string") then
		error( "squadai: assert_isstr. got "..type(arg).." instead. Value:"..tostring(arg).." "..message, 3 )
	end

end

function assert_istable( arg, message )
	
	if (type(arg) ~= "table") then
		error( "squadai: assert_istable got "..type(arg).." instead. Value:"..tostring(arg).." "..message, 3 )
	end

end



------------------------------------------------------------------------------
-- 

ET_All = {ET_Core, ET_Scout, ET_RFlank, ET_LFlank}

------------------------------------------------------------------------------
-- actions

function ACTION_STOP()

	return {
		type			= "stop", 
	}
	
end

function ACTION_WAIT_PRECISE( delay_seconds )

	assert_isnum( delay_seconds, "ACTION_WAIT_PRECISE" )
	
	return {
		type			= "wait", 
		
		isRandom		= false,
		delaySeconds	= delay_seconds,
	}
	
end

function ACTION_WAIT_RANDOM( min_delay_seconds, max_delay_seconds )

	assert_isnum( min_delay_seconds, "ACTION_WAIT_RANDOM" )
	assert_isnum( max_delay_seconds, "ACTION_WAIT_RANDOM" )

	return {
		type			= "wait", 
		
		isRandom		= true,
		minDelaySeconds	= min_delay_seconds,
		delaySeconds	= max_delay_seconds,
	}

end

function ACTION_SET_POSTURE( posture_name, duration_seconds )

	assert_isstr( posture_name, "ACTION_SET_POSTURE" )
	assert_isnum( duration_seconds, "ACTION_SET_POSTURE" )
	
	return {
		type		= "set_posture",
		
		posture		= posture_name,
		duration	= duration_seconds,
	}

end

function ACTION_MOVE_POSTURE( distance_from, distance_percentage, cover_search_radius, cover_search_angle, formation_name, desired_pace, desired_min_pace, destination_posture, destination_min_posture, max_order_delay )

	assert_isnum( distance_from, "ACTION_MOVE_POSTURE" )
	assert_isnum( distance_percentage, "ACTION_MOVE_POSTURE" )
	assert_isnum( cover_search_radius, "ACTION_MOVE_POSTURE" )
	assert_isnum( cover_search_angle, "ACTION_MOVE_POSTURE" )
	assert_isstr( formation_name, "ACTION_MOVE_POSTURE" )
	assert_isnum( desired_pace, "ACTION_MOVE_POSTURE" )
	assert_isnum( desired_min_pace, "ACTION_MOVE_POSTURE" )
	assert_isnum( destination_posture,  "ACTION_MOVE_POSTURE" )
	assert_isnum( destination_min_posture,  "ACTION_MOVE_POSTURE" )
	assert_isnum( max_order_delay, "ACTION_MOVE_POSTURE" )

	return {
		type					= "move",
		
		distanceFrom 			= distance_from,
		distancePercentage		= distance_percentage,
		
		coverSearchRadius		= cover_search_radius,
		coverSearchAngle 		= cover_search_angle,
		
		minDistFromTarget       = 5,
		
		formation				= formation_name,
		
		posture = 
		{
			desiredPace				= desired_pace,
			desiredMinPace			= desired_min_pace,
			destinationPosture		= destination_posture,
			destinationMinPosture	= destination_min_posture,
		},
		
		maxOrderDelay			= max_order_delay,
	}

end

function ACTION_MOVE_POSTURE_EXT( distance_from, distance_percentage, cover_search_radius, cover_search_angle, formation_name, desired_pace, desired_min_pace, destination_posture, destination_min_posture, max_order_delay, allow_backwards, allow_leave_los, always_move )

	assert_isnum( distance_from, "ACTION_MOVE_POSTURE_EXT-distance_from" )
	assert_isnum( distance_percentage, "ACTION_MOVE_POSTURE_EXT-distance_percentage" )
	assert_isnum( cover_search_radius, "ACTION_MOVE_POSTURE_EXT-cover_search_radius" )
	assert_isnum( cover_search_angle, "ACTION_MOVE_POSTURE_EXT-cover_search_angle" )
	assert_isstr( formation_name, "ACTION_MOVE_POSTURE_EXT-formation_name" )
	assert_isnum( desired_pace, "ACTION_MOVE_POSTURE_EXT-desired_pace" )
	assert_isnum( desired_min_pace, "ACTION_MOVE_POSTURE_EXT-desired_min_pace" )
	assert_isnum( destination_posture,  "ACTION_MOVE_POSTURE_EXT-destination_posture" )
	assert_isnum( destination_min_posture,  "ACTION_MOVE_POSTURE_EXT-destination_min_posture" )
	assert_isnum( max_order_delay, "ACTION_MOVE_POSTURE_EXT-max_order_delay" )
	assert_isbool( allow_backwards, "ACTION_MOVE_POSTURE_EXT-allow_backwards" )
	assert_isbool( allow_leave_los, "ACTION_MOVE_POSTURE_EXT-allow_leave_los" )
	assert_isbool( always_move, "ACTION_MOVE_POSTURE_EXT-always_move" )
	
	return {
		type					= "move",
		
		distanceFrom 			= distance_from,
		distancePercentage		= distance_percentage,
		
		coverSearchRadius		= cover_search_radius,
		coverSearchAngle 		= cover_search_angle,
		
		minDistFromTarget       = 5,
		
		formation				= formation_name,
		
		posture = 
		{
			desiredPace				= desired_pace,
			desiredMinPace			= desired_min_pace,
			
			destinationPosture		= destination_posture,
			destinationMinPosture	= destination_min_posture,
		},
		
		maxOrderDelay			= max_order_delay,
		
		allowBackwards			= allow_backwards,	
		allowLeaveLOS			= allow_leave_los,
		alwaysMove				= always_move,
	}

end

function ACTION_MOVE_VEHICLE( distance_from, distance_percentage, cover_search_radius, cover_search_angle, formation_name, max_order_delay )

	assert_isnum( distance_from, "ACTION_MOVE_VEHICLE" )
	assert_isnum( distance_percentage, "ACTION_MOVE_VEHICLE" )
	assert_isnum( cover_search_radius, "ACTION_MOVE_VEHICLE" )
	assert_isnum( cover_search_angle, "ACTION_MOVE_VEHICLE" )
	assert_isstr( formation_name, "ACTION_MOVE_VEHICLE" )
	assert_isnum( max_order_delay, "ACTION_MOVE_VEHICLE" )
	
	return {
		type					= "move",
		
		distanceFrom 			= distance_from,
		distancePercentage		= distance_percentage,
		
		coverSearchRadius		= cover_search_radius,
		coverSearchAngle 		= cover_search_angle,
		
		minDistFromTarget       = 10,
		
		formation				= formation_name,
		
		maxOrderDelay			= max_order_delay,
	}

end

function ACTION_MOVE_VEHICLE_EXT( distance_from, distance_percentage, cover_search_radius, cover_search_angle, formation_name, max_order_delay, allow_backwards, allow_leave_los, always_move )

	assert_isnum( distance_from, "ACTION_MOVE_VEHICLE_EXT" )
	assert_isnum( distance_percentage, "ACTION_MOVE_VEHICLE_EXT" )
	assert_isnum( cover_search_radius, "ACTION_MOVE_VEHICLE_EXT" )
	assert_isnum( cover_search_angle, "ACTION_MOVE_VEHICLE_EXT" )
	assert_isstr( formation_name, "ACTION_MOVE_VEHICLE_EXT" )
	assert_isnum( max_order_delay, "ACTION_MOVE_VEHICLE_EXT" )
	assert_isbool( allow_backwards, "ACTION_MOVE_POSTURE_EXT" )
	assert_isbool( allow_leave_los, "ACTION_MOVE_POSTURE_EXT" )
	assert_isbool( always_move, "ACTION_MOVE_POSTURE_EXT" )
	
	return {
		type					= "move",
		
		distanceFrom 			= distance_from,
		distancePercentage		= distance_percentage,
		
		coverSearchRadius		= cover_search_radius,
		coverSearchAngle 		= cover_search_angle,
		
		minDistFromTarget       = 10,
		
		formation				= formation_name,
		
		maxOrderDelay			= max_order_delay,
		
		allowBackwards			= allow_backwards,	
		allowLeaveLOS			= allow_leave_los,
		alwaysMove				= always_move,
	}

end

function ACTION_MOVE_LOS( max_order_delay )

	assert_isnum( max_order_delay, "ACTION_MOVE_LOS" )
	
	return {
		type					= "move",

		distanceFrom 			= DT_LOS,
		distancePercentage 		= 1.0,
		
		maxOrderDelay			= max_order_delay,
	}

end

function ACTION_DO_ABILITY( ability_name, max_casters )

	assert_isstr( ability_name, "ACTION_DO_ABILITY" )
	assert_isnum( max_casters, "ACTION_DO_ABILITY" )

	return {
		type 		= "do_ability",
		ability 	= ability_name,
		maxCasters	= max_casters,
	}

end

function ACTION_DO_CRITICAL( critical_name, id_name )

	assert_isstr( critical_name, "ACTION_DO_CRITICAL" )
	assert_isstr( id_name, "ACTION_DO_CRITICAL" )
	
	return { 
		type		= "do_critical", 
		critical 	= critical_name,
		id			= id_name,
		}
end

function ACTION_UNDO_CRITICAL( id_name )

	assert_isstr( id_name, "ACTION_DO_CRITICAL" )
	
	return {
		type	= "undo_critical",
		id		= id_name 
	}

end

function ACTION_UNDO_ALL_CRITICALS()

	return {
		type		= "undo_critical",
		remove_all	= true,
	}

end

function ACTION_SET_PHASE_ANIM_STATE( statemachine, statename, statename_phase_end )

	return {
		type		= "set_phase_anim",
		state_machine	= statemachine,
		state_name		= statename,
		state_name_phase_end = statename_phase_end,
	}

end

------------------------------------------------------------------------------
-- phases

function PHASE_WAIT_PRECISE( delay_seconds )
	
	assert_isnum( delay_seconds, "PHASE_WAIT_PRECISE" )

	return {
		type = DATA_PHASE,
		{
			apply_to = ET_All,
			actions = 
			{ 
				ACTION_WAIT_PRECISE( delay_seconds ),
			},
		},
	}

end

function PHASE_LEAP_FROG_ABILITY( phase_name, distance_type, distance_percentage_start, distance_percentage_end, cover_search_radius, cover_search_angle, formation_name, desired_pace, destination_posture, max_order_delay, ability_name, ability_casters, casters_per_element, num_leap_frogs )

	assert_isstr( phase_name, "PHASE_LEAP_FROG_ABILITY-phase_name" )
	assert_isnum( distance_type, "PHASE_LEAP_FROG_ABILITY-distance_type" )
	assert_isnum( distance_percentage_start, "PHASE_LEAP_FROG_ABILITY-distance_percentage_start" )
	assert_isnum( distance_percentage_end, "PHASE_LEAP_FROG_ABILITY-distance_percentage_end" )
	assert_isnum( cover_search_radius, "PHASE_LEAP_FROG_ABILITY-cover_search_radius" )
	assert_isnum( cover_search_angle, "PHASE_LEAP_FROG_ABILITY-cover_search_angle" )
	assert_isstr( formation_name, "PHASE_LEAP_FROG_ABILITY-formation_name" )
	assert_isnum( desired_pace, "PHASE_LEAP_FROG_ABILITY-desired_pace" )
	assert_isnum( destination_posture, "PHASE_LEAP_FROG_ABILITY-destination_posture" )
	assert_isnum( max_order_delay, "PHASE_LEAP_FROG_ABILITY-max_order_delay" )
	assert_isstr( ability_name, "PHASE_LEAP_FROG_ABILITY-ability_name" )
	assert_istable( ability_casters, "PHASE_LEAP_FROG_ABILITY-ability_casters" )
	assert_isnum( casters_per_element, "PHASE_LEAP_FROG_ABILITY-casters_per_element" )
	assert_isnum( num_leap_frogs, "PHASE_LEAP_FROG_ABILITY-num_leap_frogs" )
	
	return { 
		type = LEAPFROG_PHASE,
		name = phase_name,
		
		-- leap frog vars
		distanceType 			= distance_type,
		distancePercentageStart	= distance_percentage_start,
		distancePercentageEnd	= distance_percentage_end,
		
		coverSearchRadius 		= cover_search_radius,
		coverSearchAngle		= cover_search_angle,
		
		formation 				= formation_name,
		
		desiredPace 			= desired_pace,
		destinationPosture 		= destination_posture,
		
		maxOrderDelay			= max_order_delay,
		
		waitSeconds 			= 0.0,
		
		waitAbility 			= ability_name,
		waitAbilityCasters		= ability_casters,
		waitAbilityCastersPerElement = casters_per_element,		
		
		numLeapFrogs			= num_leap_frogs,
	}

end

function PHASE_GOTO( phase_name, target_phase_name )

	assert_isstr( phase_name, "PHASE_GOTO" )
	assert_isstr( target_phase_name, "PHASE_GOTO" )
	
	return { 
		type = GOTO_PHASE,
		name = phase_name,
		
		-- goto var
		targetPhaseName = target_phase_name,
	}

end
