extends Spatial


onready var exhaust_node = $Exhaust;

const ACCEL = 0.1; #24.5;  # Unit: m/s^2
const MAX_DV = 0.2;#3300.0; # Delta V in m/s
const MAX_TURN_RATE = 1.0; # Universal turn rate in °/s^2

var MISSILE_ID = "UNKNOWN";
var is_operational: bool = true;  # if the missile is operational
var has_fuel: bool = true;

var turn_instruction: Vector3 = Vector3(0, 0, 0);  # vector of (X, Y, Z) possible rotational thrust to apply (0.0 to 1.0 for full turn)
var thrust_instruction: float = 0.5;  # throttle between 0.0 and 1.0 of available thrust to apply

var curr_rotation_vel: Vector3 = Vector3();
var curr_thrust: float = 0.0;
var curr_velocity: Vector3 = Vector3();
var curr_DV: float = MAX_DV;

var __curr_shader_param_cache = {};

func _set_thruster_thrust(node: MeshInstance, power):
	#print("Node: ", node.name)
	var MAX_POWER = 10;
	if node.name in __curr_shader_param_cache:
		if __curr_shader_param_cache[node.name] == power:
			#print("Skipped shader edit");
			pass;#return;
	
	### DEBUG CODE
	#if node.name in __curr_shader_param_cache:
		#print("Editing "+node.name+" because "+str(__curr_shader_param_cache[node.name])+" != "+str(power)+" (old vs new)");
	###
	__curr_shader_param_cache[node.name] = power;
			
			
	node.get_surface_material(0).set_shader_param("power", clamp(power, .0, MAX_POWER));
		
	var particle_node: Particles = node.get_node("./Particles");
		
	if power < 2.0:
		if power == 0.0:
			node.set_visible(false);
		particle_node.set_emitting(false);
	else:
		node.set_visible(true);
		particle_node.set_emitting(true);

# Set the visual main engine flare from 0.0 to 10.0
# 0.0 turns off all engine effects
func set_main_engine_thrust(power: float):
	var exhausts = exhaust_node.get_node("Main").get_children();
	#print("Changing main exhaust to: ", power);
	
	for node in exhausts:
		self._set_thruster_thrust(node, power);

# Set the visual rotational engine flare from -10.0 to 10.0
# Negative power visualizes downwards, Positive upwards and 0.0 turns all X thrusters off
func set_X_rotational_thrust(power: float):
	var up_rotation_thrusters = [exhaust_node.get_node("FrontThrusters/ThrusterBottom"), exhaust_node.get_node("RearThrusters/ThrusterTop")];
	var down_rotation_thrusters = [exhaust_node.get_node("FrontThrusters/ThrusterTop"), exhaust_node.get_node("RearThrusters/ThrusterBottom")];
	
	if power > 0.0:
		#print("Changing rotation thrust upwards to: ", power);
		for node in up_rotation_thrusters:
			self._set_thruster_thrust(node, power);
		for node in down_rotation_thrusters:
			self._set_thruster_thrust(node, 0.0);
	elif power < 0.0:
		#print("Changing rotation thrust downwards to: ", power);
		for node in down_rotation_thrusters:
			self._set_thruster_thrust(node, -1 * power);
		for node in up_rotation_thrusters:
			self._set_thruster_thrust(node, 0.0);
	else:
		#print("Turning X rotation thrusters off");
		for node in up_rotation_thrusters+down_rotation_thrusters:
			self._set_thruster_thrust(node, 0.0);


# Set the visual rotational engine flare from -10.0 to 10.0
# Negative power visualizes left, Positive right and 0.0 turns all Y thrusters off
func set_Y_rotational_thrust(power: float):
	var MAX_POWER = 10;
	var left_rotation_thrusters = [exhaust_node.get_node("FrontThrusters/ThrusterLeft"), exhaust_node.get_node("RearThrusters/ThrusterRight")];
	var right_rotation_thrusters = [exhaust_node.get_node("FrontThrusters/ThrusterRight"), exhaust_node.get_node("RearThrusters/ThrusterLeft")];
	
	if power > 0.0:
		#print("Changing rotation thrust right to: ", power);
		for node in right_rotation_thrusters:
			self._set_thruster_thrust(node, power);
		for node in left_rotation_thrusters:
			self._set_thruster_thrust(node, 0.0);
	elif power < 0.0:
		#print("Changing rotation thrust left to: ", power);
		for node in left_rotation_thrusters:
			self._set_thruster_thrust(node, -1 * power);
		for node in right_rotation_thrusters:
			self._set_thruster_thrust(node, 0.0);
	else:
		#print("Turning Y rotation thrusters off");
		for node in right_rotation_thrusters+left_rotation_thrusters:
			self._set_thruster_thrust(node, 0.0);



func _ready():
	set_main_engine_thrust(0.0);
	set_X_rotational_thrust(0.0);
	set_Y_rotational_thrust(0.0);

var timer = 0.0;
func _physics_process(delta):
	timer -= delta;
	
	if not self.has_fuel or not self.is_operational:
		if timer <= 0.0:  
			set_main_engine_thrust(0.0);
			set_X_rotational_thrust(0.0);
			set_Y_rotational_thrust(0.0);
			
			timer = 1.0
	else:
		if timer <= 0.0:
			set_X_rotational_thrust(lerp(0.0, 10.0, turn_instruction.x));
			set_Y_rotational_thrust(lerp(0.0, 10.0, turn_instruction.y));
			set_main_engine_thrust(lerp(0.0, 10.0, thrust_instruction));
			self.transform = self.transform.orthonormalized();
			### DEBUG CODE
			#print("Rotation: "+str(self.curr_rotation_vel)+", Velocity: "+str(self.curr_velocity)+" Remeining dV: "+str(self.curr_DV));
			###
			
			timer = 1.0;
		
		self.curr_rotation_vel += turn_instruction * Vector3(MAX_TURN_RATE, MAX_TURN_RATE, MAX_TURN_RATE) * delta;
		self.curr_thrust = thrust_instruction * ACCEL * delta;
		self.curr_velocity += self.global_transform.basis.z * self.curr_thrust * -1;
		self.curr_DV -= curr_thrust;
		
		if curr_DV <= 0.0:
			print("Missile "+MISSILE_ID+" has run out of fuel!");
			self.has_fuel = false;
		
	
	if self.curr_rotation_vel.length() > 0.0:
		self.rotate_x(deg2rad(self.curr_rotation_vel.x));
		self.rotate_y(deg2rad(self.curr_rotation_vel.y));
		self.rotate_z(deg2rad(self.curr_rotation_vel.z));
	if self.curr_velocity.length() > 0.0:
		#self.translate(self.curr_velocity);
		self.global_translate(self.curr_velocity);
