/*
   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_Group
#define GUARD_Group

#include "GenericHandle.h"
#include "Enums.h"
#include "Group_Base.h"

#include <string>

using std::string;

class Group
{
public:
	Group(UnitType iType, int iMySide, int iMyGroup, const string& iName, const string& iAIFilename, int iParentCaSh, const vector<int>& savedGroupsVec, CoordsInt iStartingCoords);
	//for capital ships
	Group(UnitType iType, int iMySide, int iMyGroup, const string& iName, const string& iAIFilename, CapShipType iCaShType, const vector<int>& savedGroupsVec, CoordsInt iStartingCoords);

	void GroupAddDelInform(int groupNumber, int addOrDelete) {hGroup->GroupAddDelInform(groupNumber, addOrDelete);}

	void SetLaunchWait() {hGroup->SetLaunchWait();}
	bool SetPos(float ix, float iy) {return hGroup->SetPos(ix, iy);}
	bool GoToStartCoords() {return hGroup->GoToStartCoords();}
	void InitAI(int iAIStagger) {hGroup->InitAI(iAIStagger);}

	void MouseD(Uint8 button, Uint16 x, Uint16 y) {hGroup->MouseD(button, x, y);}
	void MouseU(Uint8 button, Uint16 x, Uint16 y) {hGroup->MouseU(button, x, y);}
	void Select(WindowChoice infoType) {hGroup->Select(infoType);}
	void Unselect() {hGroup->selected = false;}
	
	void Drag(int state, int x, int y) {hGroup->Drag(state, x, y);}

	void RunGroupAI() {if (hGroup->alive) hGroup->RunGroupAI();}
	void Move() {if (hGroup->alive) hGroup->Move();}
	void RunFireCommands() {if (hGroup->alive) hGroup->RunFireCommands();}
	void FiredAt(TargetDesc& targetInfo) {hGroup->FiredAt(targetInfo);}
	void BeenHit(int whichUnit, int power) {if (hGroup->alive) hGroup->units[whichUnit].BeenHit(power);}

	void Upkeep() {if (hGroup->alive) hGroup->Upkeep(); else hGroup->DeadUpkeep();}

	//don't check alive, we might want to draw explosions
	//therefore leave checking for alive to individual units
	void SetUSRect() {hGroup->SetUSRect();}
	void DrawSelfBackBack() {hGroup->DrawSelfBackBack();}
	void DrawSelfBack() {hGroup->DrawSelfBack();}
	void DrawSelfMiddle() {hGroup->DrawSelfMiddle();}
	void DrawSelfFront() {hGroup->DrawSelfFront(); if (hGroup->alive) hGroup->DrawBound();}
	void DrawSelfPixels() {hGroup->DrawSelfPixels();}

	//for ForceSelect
	void DrawUnitPic(int x, int y) {hGroup->units[0].DrawUnitPic(x, y);}

	void ToggleDrawBound() {hGroup->ToggleDrawBound();}
	void ToggleDrawNumber() {hGroup->ToggleDrawNumber();}
	void ResetForBattle() {hGroup->ResetForBattle();}

	//called by individual units for cap ship + frigate groups
	void FindInRange(vector<CoordsInt>& inRange, CoordsInt& myCoords, int range) {hGroup->FindInRange(inRange, myCoords, range);}
	void PointsValueCheck() {hGroup->PointsValueCheck();}
	
	void ReportOnScriptError(const char* error) {hGroup->ReportOnScriptError(error);}

	//Get
	int GetPointsValue() const {return hGroup->GetPointsValue();}
	int GetUnitPointsValue() const {return hGroup->units[0].GetPointsValue();}
	int GetUnitMaxPoints() const {return hGroup->units[0].GetMaxPoints();}
	CoordsInt GetCenter() const {return hGroup->GetCenter();}
	/*
	ish - ignores both: 
	a) fact that we test from your centre, not your nearest side
	b) only returns mid point of closest side, not the actual closest point
	*/
	CoordsInt GetClosestPoint(const CoordsInt you) const {return hGroup->GetClosestPoint(you);}
	CoordsInt GetUnitCenter(int whichUnit) const {return hGroup->units[whichUnit].GetCenter();}
	void GetDimensions(int& giveWidth, int& giveHeight) const {giveWidth = hGroup->width; giveHeight = hGroup->height;}
	void GetRect(SDL_Rect& giveRect) const {giveRect.x = static_cast<Sint16>(hGroup->myx); giveRect.y = static_cast<Sint16>(hGroup->myy); giveRect.w = hGroup->width; giveRect.h = hGroup->height;}
	CoordsFloat GetSpeeds() const {CoordsFloat ret = {hGroup->remSpeedx, hGroup->remSpeedy}; return ret;}
    int GetOnScreen() const {return hGroup->onScreen;}

	UnitType GetType() const {return hGroup->GetType();}
	CapShipType GetCSType() const {return hGroup->units[0].GetCSType();}

	const string GetUnitName() const {return hGroup->dataFilename;}
	string GetRealPictureName() const {return hGroup->units[0].GetRealPictureName();}
	string GetAIFilename() const {return hGroup->aiFilename;}
	int GetParentCaSh() const {return hGroup->myParentCaSh;}
	int GetScriptVar(int which) const {return hGroup->GetScriptVar(which);}
	CoordsInt GetSaveGroup(int which) const {return hGroup->GetSaveGroup(which);}
	unsigned int GetScriptTimer(int which) const {return hGroup->GetScriptTimer(which);}
	CoordsInt GetStartingCoords() const {return hGroup->startingCoords;}
	bool GetSelected() const {return hGroup->selected;}
	
	int GetHealth() const {return hGroup->GetHealth();}
	int GetShield() const {return hGroup->GetShield();}
	int GetArmour() const {return hGroup->GetArmour();}
	int GetMaxHealth() const {return hGroup->GetMaxHealth();}
	int GetMaxShield() const {return hGroup->GetMaxShield();}
	int GetMaxArmour() const {return hGroup->GetMaxArmour();}
	int GetUnitMaxShield() const {return hGroup->units[0].GetMaxShield();}
	int GetUnitMaxArmour() const {return hGroup->units[0].GetMaxArmour();}
	
	void GetShAndAr(int& giveShieldC, int& giveShieldM, int& giveShieldR, int& giveArmourC, int& giveArmourM, int whichUnit) const {hGroup->units[whichUnit].GetShAndAr(giveShieldC, giveShieldM, giveShieldR, giveArmourC, giveArmourM);}
	
	int GetSpeed() const {return static_cast<int>(hGroup->speed);}
	WeaponType GetSmallType() const {return hGroup->units[0].GetSmallType();}
	WeaponType GetBigType() const {return hGroup->units[0].GetBigType();}
	int GetBigAmmo() const {return hGroup->GetBigAmmo();}

	int GetUnitsLeft() const {return hGroup->unitsLeft;}

	string GetEngineName() const {return hGroup->units[0].GetEngineName();}
	string GetShieldName() const {return hGroup->units[0].GetShieldName();}
	string GetArmourName() const {return hGroup->units[0].GetArmourName();}
	int GetSmallNumber() const {return hGroup->units[0].GetSmallNumber();}

	//works on basis only one cap ship per cap ship group
	int GetCapacity() const {return hGroup->units[0].GetCapacity();}
	int GetFrCapacity() const {return hGroup->units[0].GetFrCapacity();}
	
	int GetHowFull() const {return hGroup->GetHowFull();}

	void GetWeapCoords(vector<CoordsInt>& giveSmall, CoordsInt& giveBig) const {return hGroup->units[0].GetWeapCoords(giveSmall, giveBig);}

	int GetAlive() const {return hGroup->alive;}
	int GetUnitAlive(int whichUnit) const {return hGroup->units[whichUnit].GetAlive();}

	bool GetSpeedPlaneMatchesTarget() const {return hGroup->speedPlaneMatchesTarget;}

	const AICommands* GetTheCommands() const {return &(hGroup->theCommands);}
	
	bool CheckForCollision(int nSide, int nGroup) const {return hGroup->CheckForCollision(nSide, nGroup);}
	
	//for debugging
	int GetAIStagger() const {return hGroup->aiStagger;}

	//Change
	void ChangeSize(int newSize) {hGroup->ChangeSize(newSize);}
	void ChangeStartCoords(int x, int y) {hGroup->ChangeStartCoords(x, y);}
	void ChangeUnitPic(const string& newPic) {hGroup->ChangeUnitPic(newPic);}
	void ChangeSmallType(WeaponType newType) {hGroup->ChangeSmallType(newType);}
	void ChangeBigType(WeaponType newType) {hGroup->ChangeBigType(newType);}
	void ChangeEngine(const string& newStat) {hGroup->ChangeEngine(newStat);}
	void ChangeArmour(const string& newStat) {hGroup->ChangeArmour(newStat);}
	void ChangeShield(const string& newStat) {hGroup->ChangeShield(newStat);}
	void ChangeCSType(CapShipType newStat) {hGroup->ChangeCSType(newStat);}

	void ChangeParentCaSh(int newParent) {hGroup->myParentCaSh = newParent;}
	void ChangeAIScript(const string& newAIScript) {hGroup->aiFilename = newAIScript;}

	void ChangeSaveGroup(int which, const CoordsInt& newSavedGroup) {hGroup->ChangeSaveGroup(which, newSavedGroup);}
	
	void ChangeMySide(int newMySide) {hGroup->ChangeMySide(newMySide);}

private:
	GenericHandle<Group_Base> hGroup;
};

#endif
