/*
   Copyright (C) 2004 by James Gregory
   Part of the GalaxyHack project
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License.
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY.
 
   See the COPYING file for more details.
*/

#ifndef GUARD_Projectile
#define GUARD_Projectile

#include "RTSStructs.h"
#include "GenericHandle.h"

//forward declarations:
class Projectile;
class Projectile_Base;
class LaserBolt;

class Projectile_Base {
public:
	Projectile_Base(float ix, float iy, CoordsInt target, WeaponType iType, Uint16 iColor);
	//for explosions
	Projectile_Base(float ix, float iy);
	virtual ~Projectile_Base() {}

	static void DrawBigLaser(int x0, int y0, int x1, int y1, Uint16 color);

	static bool CheckToHit(int accuracy, int difficulty);

	virtual bool Move();

	//blank versions exist
	virtual void DrawSelfPixels() {}
	virtual void DrawSelfBitmap() {}

	virtual WeaponCat GetType() const = 0;
	CoordsInt GetTarget() const {CoordsInt ret = {targetSide, targetGroup};	return ret;}

protected:
	static int ClipLine(int& x1, int& y1,int& x2, int& y2);
	static void DrawLine(int x0, int y0, int x1, int y1, Uint16 color);

	void StandardLineDraw();

	void PropsToSpeedAndLength(float dx, float dy);
	void SetDuration(float distance);

	//must be floats or projectiles often look like they miss totally
	float x;
	float y;
	float speedx;
	float speedy;
	int lengthx;
	int lengthy;

	int timer;
	int duration;
	bool weHit;

	TargetDesc targetInfo;
	int targetSide;
	int targetGroup;
	int targetUnit;
	float mySpeed;
	int myLength;
	WeaponType myType;

	Uint16 color;
};

class LaserBolt_Base: public Projectile_Base {
public:
	LaserBolt_Base(float ix, float iy, CoordsInt target, WeaponType iType, Uint16 iColor);

	void PredictTarget();

	virtual void DrawSelfPixels() = 0;
};

class SmallLaserBolt: public LaserBolt_Base {
public:
	SmallLaserBolt(float ix, float iy, CoordsInt target, WeaponType iType, Uint16 iColor);

	void DrawSelfPixels();

	WeaponCat GetType() const {return WCAT_Small;}
};

class TwinLaserBolt: public LaserBolt_Base {
public:
	TwinLaserBolt(float ix, float iy, CoordsInt target, WeaponType iType, Uint16 iColor);

	void DrawSelfPixels();

	WeaponCat GetType() const {return WCAT_Twin;}
};

class Missile: public Projectile_Base {
public:
	Missile(float ix, float iy, CoordsInt target, WeaponType iType);

	bool Move();
	void DrawSelfPixels();

	WeaponCat GetType() const {return WCAT_Missile;}

private:
	CoordsInt targetCoords;
	bool exploding;
	bool targetDead;
};

class Torpedo: public Projectile_Base {
public:
	Torpedo(float ix, float iy, CoordsInt target, WeaponType iType);

	bool Move();
	void DrawSelfPixels();
	void DrawSelfBitmap();
	
	WeaponCat GetType() const {return WCAT_Torpedo;}

protected:
	bool exploding;
	unsigned int explodeTimer;
};

class LaserExplosion: public Projectile_Base {
public:
	LaserExplosion(float ix, float iy);
	bool Move();
	void DrawSelfBitmap();

	WeaponCat GetType() const {return WCAT_Explosion;}	

protected:
	unsigned int explodeTimer;
};

class Projectile {
public:
	Projectile(float ix, float iy, CoordsInt target, WeaponType iType, Uint16 iColor);
	//for explosions
	Projectile(float ix, float iy);

	bool Move() {return hProj->Move();}

	//these return 0 if an animation is finished and wants
	//to be destroyed
	void DrawSelfPixels() {hProj->DrawSelfPixels();}
	void DrawSelfBitmap() {hProj->DrawSelfBitmap();}

	WeaponCat GetType() {return hProj->GetType();}
	CoordsInt GetTarget() {return hProj->GetTarget();}

protected:
	GenericHandle<Projectile_Base> hProj;
};

#endif

