/** 
 *  _   _        _  _                           _             
 * | |_| |  ___ | || |  ___   __ _  _ __  _ __ (_)  ___  _ __ 
 * |  _  | / _ \| || | / __| / _` || '__|| '__|| | / _ \| '__|
 * | | | ||  __/| || || (__ | (_| || |   | |   | ||  __/| |   
 * |_| |_| \___||_||_| \___| \__,_||_|   |_|   |_| \___||_|   
 * 
 *  (c) 2001 Free Lunch Design, Teknisk-IT, AerotechTelub
 *			  http://www.freelunchdesign.com
 * 
 * This source code is released as is under GPL (General Public
 * License). Please refer to license.txt for more information.
 * 
 */
 
#include <stdio.h>
#include <math.h>
#include "allegro.h"
#include "unit.h"
#include "vehicle.h"
#include "soldier.h"
#include "pickup.h"


// constructor
unit :: unit() {}

// destructor
unit :: ~unit() {}

void unit::evaluate_AI() {
	switch(AI_mode) {
		case AI_HUNT:
			// if enemy lost
			// AI_mode = AI_IDLE;
			// if enemy within firing range
			// AI_mode = AI_ATTACK;
			break;

		case AI_ATTACK:
			// if outside firing range
			// AI_mode = AI_HUNT;
			break;

		case AI_TRAVEL:
			// if enemy sighted
			// lock enemy
			// AI_mode = AI_HUNT
			// if reached waypoint
			// AI_mode = AI_IDLE;
			break;

		default:	// AI_IDLE || undef
			if (AI_mode != AI_IDLE) AI_mode = AI_IDLE;
			// if enemy sighted
			// lock enemy
			// AI_mode = AI_HUNT;
			// else if got waypoint
			// lock waypoin
			// AI_mode = AI_TRAVEL;
			// fix error in AI

			break;
	}
}

void unit::reset_wp() {
	for(int i=0;i<MAX_WAYPOINTS;i++) wp[i].active = FALSE;
}

void unit::update_movement() {
	if (target_thrust == 0) thr_str = 0;
	else {
		if (thr_str > target_thrust) thrust(1);
		if (thr_str < target_thrust) thrust(-1);
	}

	if (angle > target_angle+ftofix(0.5)) rotate(-1);
	if (angle < target_angle-ftofix(0.5)) rotate(1);
	

	if (type == OBJ_TANK || type == OBJ_TOWER) {
		vehicle *v = (vehicle *)this;
		if (v->turret_angle < v->turret_target_angle) v->turret_angle += itofix(v->turret_turn_speed)/2;
		if (v->turret_angle > v->turret_target_angle) v->turret_angle -= itofix(v->turret_turn_speed)/2;
	}
}

void unit::act_on_object(object *o) {
	double hyp = 0;
	double a = 42;

	// is object 3D?
	if (o->altitude > GL_GROUND_FLAT_SCENERY) {//o->type == OBJ_SOLDIER || o->type == OBJ_FOOT_SOLDIER || o->type == OBJ_BAZOOKA_SOLDIER || o->type == OBJ_JEEP || o->type == OBJ_TRUCK || o->type == OBJ_TANK || o->type == OBJ_TOWER || o->type == OBJ_HELI || o->type == OBJ_BUILDING) {
		double dx  = x - o->x;
		double dy  = y - o->y;
		hyp = sqrt(dx*dx + dy*dy);
	
		// is unit friend or foe?
		if (o->team != team && o->type != OBJ_SCENERY && o->type != OBJ_PICKUP) {
			// is unit more dangerous then current?
			if (o->is_more_dangerous_than(current_target, type)) {
				// is unit within sight?
				if (hyp < sight_range) {  // enemy spotted
					target_thrust = 1;
					
					if (a == 42) a = atan2(dy, dx);
	
					// turn towards it
					target_angle = ftofix(((a-PI/2) * 256)/(2 * PI));
					if (ABS(target_angle - angle) > itofix(128))  {
						if (target_angle > angle) target_angle -= itofix(256);
						else target_angle += itofix(256);
					}
	
					// is unit within fire range?
					if (hyp < fire_range && is_armed()) {  // fire in the hole!
						target_thrust = 0.3;
						current_target = o;
						// use turret if available
						if (type == OBJ_TANK || type == OBJ_TOWER) {
							vehicle *v = (vehicle *)this;
							v->turret_target_angle = target_angle;
	
							if (v->turret_angle > v->turret_target_angle - itofix(5) && v->turret_angle < v->turret_target_angle + itofix(5)) may_fire = TRUE;
						}
						else {
							if (angle > target_angle - itofix(5) && angle < target_angle + itofix(5)) may_fire = TRUE;
							if (type == OBJ_SOLDIER || type == OBJ_FOOT_SOLDIER || type == OBJ_BAZOOKA_SOLDIER) {
								if (((soldier *)this)->burning) may_fire = FALSE;
							}
								
						}
						if (fire_rate == 0) may_fire = FALSE;
					}
				}				
			}
		}

		
		// don't walk into it
		if (hyp < o->radius+10 && (o->type != OBJ_HELI || type == OBJ_SOLDIER || type == OBJ_FOOT_SOLDIER || type == OBJ_BAZOOKA_SOLDIER)) {  // collision!
			if (type == OBJ_SOLDIER || type == OBJ_FOOT_SOLDIER || type == OBJ_BAZOOKA_SOLDIER) target_thrust = 4;
			else target_thrust = 1;
			if (a == 42) a = atan2(dy, dx);

			if (hyp < o->radius && (o->type == OBJ_JEEP || o->type == OBJ_TANK || o->type == OBJ_TRUCK)) jumping = TRUE;

			// fix angle to turn away
			target_angle = ftofix(((a+PI/2) * 256)/(2 * PI));
			if (ABS(target_angle - angle) > itofix(128))  {
				if (target_angle > angle) target_angle -= itofix(256);
				else target_angle += itofix(256);
			}
		}

		if (type == OBJ_FOOT_SOLDIER && o->type == OBJ_PICKUP && hyp < 200) {
			soldier *s = (soldier *)this;
			if (s->pup_collector && !s->carrying_pup) {
				if (hyp < 10) { // take pickup
					pickup *p = (pickup *)o;
					s->carrying_pup = p->p_type;
					p->sect->remove_object(p);
					p->current_mission->obj[p->index] = NULL;
					p->~pickup();
				}
				else { // go there
					if (a == 42) a = atan2(dy, dx);
					target_thrust = 6;
					target_angle = ftofix(((a-PI/2) * 256)/(2 * PI));
					if (ABS(target_angle - angle) > itofix(128))  {
						if (target_angle > angle) target_angle -= itofix(256);
						else target_angle += itofix(256);
					}
				}
			}
		}
		

		// get picked up?
		if ((type == OBJ_SOLDIER || type == OBJ_FOOT_SOLDIER || type == OBJ_BAZOOKA_SOLDIER) && o->type == OBJ_HELI)  {
			soldier *s = (soldier *)this;
			if (s->wanna_ride && (s->pup_collector ? s->carrying_pup : 1)) {
				vehicle *v = (vehicle*)o;
				// is heli within sight && !too close ?
				if (hyp < 200 && v->heli_altitude == 0 && (s->pup_collector ? 1 :(v->num_passengers<v->max_passengers))) {  // yes
					if (hyp < 10) {  // pickup (enter choppa)
						if (s->pup_collector) {
							s->ply->apply_pickup(s->carrying_pup);
							s->carrying_pup = 0;
							s->sect->remove_object(s);
							s->current_mission->obj[s->index] = NULL;
							s->ply->cop = s;
						}
						else if (v->add_object(this)) {
							team = v->team;
						}
					}
					else { // run there
						target_thrust = 4;  
						// turn towards it
						if (a == 42) a = atan2(dy, dx);
						target_angle = ftofix(((a-PI/2) * 256)/(2 * PI));
						if (ABS(target_angle - angle) > itofix(128))  {
							if (target_angle > angle) target_angle -= itofix(256);
							else target_angle += itofix(256);
						}
					}
				} 
			}
		}
	}
}