/*
   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 "Globals.h"
#include "Group.h"

#include <string>

using std::string;

SmShGroup::SmShGroup(int iMySide, int iMyGroup, const string& iDataFilename, const string& iAIFilename, int iParentCaSh, const vector<int>& savedGroupsVec, CoordsInt iStartingCoords):
Group_Base(iDataFilename, iAIFilename, iMySide, iMyGroup, savedGroupsVec, iStartingCoords), savedPropx(0), savedPropy(0) {
	myParentCaSh = iParentCaSh;

	//can't just use insert because we have to set up the reference count
	//for the picture properly
	for (int i = 0; i != ssGroupSize; ++i)
		units.push_back(RTSUnit(mySide, myGroup, UT_SmShUnit, dataFilename));

	SetInitialVars();
}

void SmShGroup::SetLaunchWait() {
	launchWait = 0;

	for (int i = 0; i != myGroup; ++i) {
		if (sides[mySide].groups[i].GetParentCaSh() == myParentCaSh)
			launchWait+= launchTimePerGroup;
	}
}

bool SmShGroup::GoToStartCoords() {
	if (myParentCaSh == -1)
		return Group_Base::GoToStartCoords();
	else
		SetPosToParentCenter();

	return true;
}

void SmShGroup::Drag(int state, int x, int y) {
	if (myParentCaSh == -1)
		Group_Base::Drag(state, x, y);

	startingCoords.x = static_cast<int>(myx - sides[mySide].startingRect.x);
	startingCoords.y = static_cast<int>(myy - sides[mySide].startingRect.y);
}

void SmShGroup::SetPosToParentCenter() {
	CoordsInt center = sides[mySide].groups[myParentCaSh].GetCenter();
	SetPos(center.x - width / 2, center.y - height / 2);
}

void SmShGroup::RunGroupAI() {
	if (!launchWait)
		Group_Base::RunGroupAI();
	else
		--launchWait;
}

void SmShGroup::ConvertCollisions() {
    if (CheckForCollision(theCommands.moveTarget.x, theCommands.moveTarget.y)) {
        theCommands.aimPropx = savedPropx;
        theCommands.aimPropy = savedPropy;
        return;
    }
    savedPropx = theCommands.aimPropx;
    savedPropy = theCommands.aimPropy;
}

void SmShGroup::SelectSmallTargets() {
	if (theCommands.moveCommand == MC_MoveGroup
			&& theCommands.moveTargetDist <= weaponLookup[units[0].GetSmallType()].range
			&& sides[theCommands.moveTarget.x].myFlag != sides[mySide].myFlag
			//if we are moving towards a saved group which has been killed then we
			//shouldn't attack it
			&& sides[theCommands.moveTarget.x].groups[theCommands.moveTarget.y].GetAlive()) {
		//loop through units
		for (int i = 0; i != units.size(); ++i)
			units[i].SelectSmallTargets(theCommands);
	}
}

void SmShGroup::ConvertFireTarget() {
	if (!theCommands.bFire)
		return;
		 
	if (theCommands.moveCommand == MC_MoveGroup && theCommands.bInverse == false) {
		theCommands.fireTarget = theCommands.moveTarget;
		theCommands.fireTargetDist = theCommands.moveTargetDist;
		
		if (weaponLookup[units[0].GetBigType()].category == WCAT_Torpedo && sides[theCommands.moveTarget.x].groups[theCommands.moveTarget.y].GetType() != UT_CaShUnit) {
			theCommands.bFire = false;
			ReportOnScriptError("Attempt to fire torpedos at non-capital ship");
		}
	} else {
		theCommands.bFire = false;
		ReportOnScriptError("Attempt to fire big weapons when not moving towards a group");
	}
}

void SmShGroup::DrawSelfBackBack() {
	if (frameCounter <= SmShBackBackTime && frameCounter && onScreen) {
		for (int i = 0; i != units.size(); ++i)
			units[i].DrawSelf();
	}
}

void SmShGroup::DrawSelfFront() {
	if (onScreen && frameCounter > SmShBackBackTime) {
		for (int i = 0; i != units.size(); ++i)
			units[i].DrawSelf();
	}
}

void SmShGroup::DrawBound() {
	//onscreen checked in base function
	if (frameCounter)
		Group_Base::DrawBound();
}

////

AutoFireGroup::AutoFireGroup(const string& iDataFilename, const string& iAIFilename, int iMySide, int iMyGroup, const vector<int>& savedGroupsVec, CoordsInt iStartingCoords):
Group_Base(iDataFilename, iAIFilename, iMySide, iMyGroup, savedGroupsVec, iStartingCoords) {}

void AutoFireGroup::SelectSmallTargets() {
	//loop through units
	for (int i = 0; i != units.size(); ++i)
		units[i].SelectSmallTargets();
}

////

FrGroup::FrGroup(int iMySide, int iMyGroup, const string& iDataFilename, const string& iAIFilename, const vector<int>& savedGroupsVec, CoordsInt iStartingCoords):
AutoFireGroup(iDataFilename, iAIFilename, iMySide, iMyGroup, savedGroupsVec, iStartingCoords) {
	//can't just use insert because we have to set up the reference count
	//for the picture properly
	for (int i = 0; i != frGroupSize; ++i)
		units.push_back(RTSUnit(mySide, myGroup, UT_FrUnit, dataFilename));

	SetInitialVars();
}

void FrGroup::DrawSelfMiddle() {
	if (onScreen) {
		for (int i = 0; i != units.size(); ++i)
			units[i].DrawSelf();
	}
}

////

CaShGroup::CaShGroup(int iMySide, int iMyGroup, const string& iDataFilename, const string& iAIFilename, CapShipType iCaShType, const vector<int>& savedGroupsVec, CoordsInt iStartingCoords):
AutoFireGroup(iDataFilename, iAIFilename, iMySide, iMyGroup, savedGroupsVec, iStartingCoords) {
	units.push_back(RTSUnit(mySide, myGroup, UT_CaShUnit, dataFilename, iCaShType));

	SetInitialVars();
}

void CaShGroup::DrawSelfBack() {
	if (onScreen) {
		for (int i = 0; i != units.size(); ++i)
			units[i].DrawSelf();
	}
}

