/* homing-missile.m,
 *
 * Homing missiles are ally projectiles that lock onto the nearest
 * enemy that it thinks it can hit.
 */

#include <math.h>
#include "common.h"
#include "debris/ir-line.h"
#include "projectiles/homing-missile.h"
#include "rotate.h"
#include "seborrhea/seborrhea.h"
#include "unit-seeking.h"

#ifdef DEBUG_HOMING_MISSILE_DEAD_MEAT_TRACKER
#include <allegro.h>
#include "map.h"
#endif


#define HOMING_MISSILE_SPEED	4.5
#define MAX_ROTATION_ANGLE	deg2rad(3.0)
#define TRACKING_DELAY		20
#define TURNING_RADIUS		(HOMING_MISSILE_SPEED/MAX_ROTATION_ANGLE)


@implementation HomingMissile
- init
{
    [super init];

    health = 3;
    speed = HOMING_MISSILE_SPEED;

    sprite = (Sebum<SebImage> *)[base_sebum getSebumByName:"weapon/homing"];
    w = [sprite width];
    h = [sprite height];
    rotatable_sprite = YES;

    drop_time = TRACKING_DELAY;
    target = nil;

    return self;
}

- (int) update
{
    if (drop_time > 0)
        drop_time--;
    else
	[spawn_debris([IRLine class], x, y, MEDIUM_LAYER) setAngle:angle];

    if (not target) {
        target = find_closest_unit_with_some_genius(x, y, angle, TURNING_RADIUS, ACTIVE_ENEMY_LISTS);
    }
    else if (not unit_exists(target, ACTIVE_ENEMY_LISTS))
	target = nil;
    else {
	double desired_angle = angle_towards_unit(x, y, target);
        limited_rotate(&angle, desired_angle, MAX_ROTATION_ANGLE);
	simplify_angle(&angle);
	recalculate_velocity = YES;
    }

    return [super update];
}

#ifdef DEBUG_HOMING_MISSILE_DEAD_MEAT_TRACKER
- (void) draw:(BITMAP *)dest
{
    [super draw:dest];

    if (target && unit_exists(target, ACTIVE_ENEMY_LISTS)) {
	double x_, y_;
	[target getX:&x_ Y:&y_];

	textprintf_centre(dest, font, x-offsetX, y-offsetY, makecol(0x00, 0x00, 0xff), "%02g", sqrt(SQ(x_-x) + SQ(y_-y)));
	line(dest, x-offsetX, y-offsetY, x_-offsetX, y_-offsetY, makecol(0xff, 0x00, 0x00));
    }

    /* Turning radiuses.  VERY large. */
    circle(dest, 
	   x-offsetX + TURNING_RADIUS*sin(angle), 
	   y-offsetY + TURNING_RADIUS*cos(angle),
	   TURNING_RADIUS, makecol(0x80, 0x00, 0x00));
    circle(dest, 
	   x-offsetX - TURNING_RADIUS*sin(angle), 
	   y-offsetY - TURNING_RADIUS*cos(angle),
	   TURNING_RADIUS, makecol(0x80, 0x00, 0x00));
}
#endif
@end

/*--------------------------------------------------------------*/

void fireHomingMissile(double x, double y, int level, int *reload, int pid)
{
#define SPAWN_ALLY_PROJ(class,x,y,theta)		[[(AllyProjectile *)spawn_projectile(class,x,y,YES) setAngle:theta] setParentID:pid]

    Class proj = [HomingMissile class];

    /* Level 0: 2 x 3 hp/shot * 50/50 shots/sec =  6.0 hp/sec.
       Level 1: 3 x 3 hp/shot * 50/50 shots/sec =  9.0 hp/sec.
       Level 2: 4 x 3 hp/shot * 50/50 shots/sec = 12.0 hp/sec.
    */

    y -= 10;
    if (level == 0) {
        SPAWN_ALLY_PROJ(proj, x-10, y, deg2rad(100.0));
        SPAWN_ALLY_PROJ(proj, x+10, y, deg2rad(80.0));
    } 
    elif (level == 1) {
        SPAWN_ALLY_PROJ(proj, x-10, y, deg2rad(110.0));
        SPAWN_ALLY_PROJ(proj, x   , y, deg2rad(90.0));
        SPAWN_ALLY_PROJ(proj, x+10, y, deg2rad(70.0));
    }
    else {
        SPAWN_ALLY_PROJ(proj, x-10, y, deg2rad(120.0));
        SPAWN_ALLY_PROJ(proj, x- 3, y, deg2rad(100.0));
        SPAWN_ALLY_PROJ(proj, x+ 3, y, deg2rad(80.0));
        SPAWN_ALLY_PROJ(proj, x+10, y, deg2rad(60.0));
    }

    *reload = 50;

#undef SPAWN_ALLY_PROJ
}
