/*
   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.
*/

#include "RTSUnit_Base.h"
#include "Globals.h"
#include "Group.h"
#include "Projectile.h"
#include "Random.h"

#include <boost/filesystem/operations.hpp>

#include <stdexcept>

using std::runtime_error;

SmallShip::SmallShip(int iMySide, int iMyGroup, const string& iName):
RTSUnit_Base(iName, iMySide, iMyGroup) {
	//load if found either in struct or on hard drive
	if (sides[mySide].sdStruct.unitData.find(name) != sides[mySide].sdStruct.unitData.end()
	        || DoesFileExist(GetFleetDir(mySide) + name + ".dat"))
		LoadData();
	else {
		myType = UT_SmShUnit;
		DefaultTypeDepStats();
		LoadPicture();
	}
}

void SmallShip::InitSmall() {
	smallStage = w_Ready;
	smallTarget.x = 0;
	smallTarget.y = 0;
}

void SmallShip::SelectSmallTargets(AICommands& theCommands) {
	if (smallStage == w_Ready) {
		smallStage = w_Aiming;

		smallTarget = theCommands.moveTarget;

		smallTimer = frameCounter;
		smallAiming = Random() % maxAiming;
	}
}

void SmallShip::Move(float distx, float disty) {
	//half the time
	if (extraMoveFrames && doExtraMove == 1) {
		distx += extraMovex;
		disty += extraMovey;
		--extraMoveFrames;

		doExtraMove = 0;
	} else
		doExtraMove = 1;

	RTSUnit_Base::Move(distx, disty);
}

void SmallShip::FireSmall(AICommands& theCommands) {
	//if our movement target is no longer the saved target, reset
	if (smallStage != w_Reloading && smallTarget != theCommands.moveTarget)
		smallStage = w_Ready;

	//else if aiming time is up and we still have a valid target...
	else if (smallStage == w_Firing) {
		if (sides[mySide].groups[myGroup].GetSpeedPlaneMatchesTarget()) {
			smallStage = w_Reloading;
			smallTimer = frameCounter;
            CoordsInt center = GetCenter();
			projectiles.push_back(Projectile(center.x, center.y, theCommands.moveTarget, smallType, sides[mySide].laserColor));
		}
		//else we wait, and with no reloading are allowed to fire as soon as we are properly aligned
	}
}

void SmallShip::Upkeep() {
	RTSUnit_Base::Upkeep();

	if (armourCurrent < 1) {
		alive = false;
		explodeTimer = ssExplodeFrames * framesPerAnimFrame;
		return;
	}

	//check for small reloading
	if (smallStage == w_Reloading && frameCounter - smallTimer > weaponLookup[smallType].reload)
		smallStage = w_Ready;

	//check for small aiming (time decided when we choose
	//a target)
	if (smallStage == w_Aiming && frameCounter - smallTimer > smallAiming)
		smallStage = w_Firing;
}

void SmallShip::Explode() {
	if (sides[mySide].groups[myGroup].GetOnScreen()) {
		if (explodeTimer > framesPerAnimFrame * 5)
			JSDL.Blt(genPictures[GENPIC_SMSHEXLODE1], USRect);
		else if (explodeTimer > framesPerAnimFrame * 4)
			JSDL.Blt(genPictures[GENPIC_SMSHEXLODE2], USRect);
		else if (explodeTimer > framesPerAnimFrame * 3)
			JSDL.Blt(genPictures[GENPIC_SMSHEXLODE3], USRect);
		else if (explodeTimer > framesPerAnimFrame * 2)
			JSDL.Blt(genPictures[GENPIC_SMSHEXLODE4], USRect);
		else if (explodeTimer > framesPerAnimFrame)
			JSDL.Blt(genPictures[GENPIC_SMSHEXLODE5], USRect);
		else
			JSDL.Blt(genPictures[GENPIC_SMSHEXLODE6], USRect);
	}
}

void SmallShip::GetWeapCoords(vector<CoordsInt>& giveSmall, CoordsInt& giveBig) const {
	throw runtime_error("Attempt to get weapon coords of a small ship");
}

void SmallShip::DefaultTypeDepStats() {
	width = SSWidth;
	height = SSHeight;
	picName = globalSettings.defaultSSPic;
	engineName = globalSettings.defaultSSEngine;
	armourName = globalSettings.defaultSSArmour;

	RTSUnit_Base::DefaultTypeDepStats();
}

void SmallShip::SetSmallNumber() {
	if (smallType == WT_None)
		smallNumber = 0;
	else
		smallNumber = 1;
}

