/*
	This file is part of Warzone 2100.
	Copyright (C) 1999-2004  Eidos Interactive
	Copyright (C) 2005-2020  Warzone 2100 Project

	Warzone 2100 is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.

	Warzone 2100 is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with Warzone 2100; if not, write to the Free Software
	Foundation, Inc. , 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
 *
 * @file
 * Function prototypes for giving droids orders.
 *
 */

#ifndef __INCLUDED_SRC_ORDER_H__
#define __INCLUDED_SRC_ORDER_H__

#include "orderdef.h"

/** Find some droid to repair, starting at (x, y) within some radius, given a player, or return nullptr.
 * Droids having full HP with order = DORDER_RTR or RTR_SPECIFIED will automatically
 * be sent to delivery point, or back to commander
 */

DROID *findSomeoneToRepair(const STRUCTURE *obj, int radius);
DROID *findSomeoneToRepair(const DROID *psTurret, int radius);

/** \brief Gives the droid an order. */
void orderDroidBase(DROID *psDroid, DROID_ORDER_DATA *psOrder);

/** \brief Checks targets of droid's order list. */
void orderCheckList(DROID *psDroid);

/** \brief Updates a droids order state. */
bool orderUpdateDroid(DROID *psDroid);

/** \brief Sends an order to a droid. */
void orderDroid(DROID *psDroid, DROID_ORDER order, QUEUE_MODE mode);

/** \brief Compares droid's order with order. */
bool orderState(const DROID *psDroid, DROID_ORDER order);

/** \brief Checks if an order is valid for a location. */
bool validOrderForLoc(DROID_ORDER order);

/** \brief Checks if an order is valid for an object. */
bool validOrderForObj(DROID_ORDER order);

/** \brief Sends an order with a location to a droid. */
void orderDroidLoc(DROID *psDroid, DROID_ORDER order, UDWORD x, UDWORD y, QUEUE_MODE mode);

/** \brief Gets the state of a droid order with a location. */
bool orderStateLoc(const DROID *psDroid, DROID_ORDER order, UDWORD *pX, UDWORD *pY);

/** \brief Sends an order with an object target to a droid. */
void orderDroidObj(DROID *psDroid, DROID_ORDER order, BASE_OBJECT *psObj, QUEUE_MODE mode);

/** \brief Gets the state of a droid's order with an object. */
BASE_OBJECT *orderStateObj(const DROID *psDroid, DROID_ORDER order);

/** \brief Sends an order with a location and a stat to a droid. */
void orderDroidStatsLocDir(DROID *psDroid, DROID_ORDER order, STRUCTURE_STATS *psStats, UDWORD x, UDWORD y, uint16_t direction, QUEUE_MODE mode);

/** \brief Gets the state of a droid order with a location and a stat. */
bool orderStateStatsLoc(const DROID *psDroid, DROID_ORDER order, STRUCTURE_STATS **ppsStats);

/** \brief Sends an order with a location and a stat to a droid. */
void orderDroidStatsTwoLocDir(DROID *psDroid, DROID_ORDER order, STRUCTURE_STATS *psStats, UDWORD x1, UDWORD y1, UDWORD x2, UDWORD y2, uint16_t direction, QUEUE_MODE mode);

/** \brief Sends an order with two locations and a stat to a droid. */
void orderDroidStatsTwoLocDirAdd(DROID *psDroid, DROID_ORDER order, STRUCTURE_STATS *psStats, UDWORD x1, UDWORD y1, UDWORD x2, UDWORD y2, uint16_t direction);

/** \brief Sends an order with a location target to all selected droids. add = true queues the order. */
void orderSelectedLoc(uint32_t player, uint32_t x, uint32_t y, bool add);

/** \brief Sends an order with an object target to all selected droids. add = true queues the order. */
void orderSelectedObj(UDWORD player, BASE_OBJECT *psObj);
void orderSelectedObjAdd(UDWORD player, BASE_OBJECT *psObj, bool add);

/** \brief Adds an order to a droids order list. */
void orderDroidAdd(DROID *psDroid, DROID_ORDER_DATA *psOrder);

/** \brief Adds a pending order to a droids order list. */
void orderDroidAddPending(DROID *psDroid, DROID_ORDER_DATA *psOrder);

/** \brief Sends the next order from a droids order list to the droid. */
bool orderDroidList(DROID *psDroid);

/** \brief Sends an order with a location and a stat to all selected droids. add = true queues the order. */
void orderSelectedStatsLocDir(UDWORD player, DROID_ORDER order, STRUCTURE_STATS *psStats, UDWORD x, UDWORD y, uint16_t direction, bool add);

/** \brief Sends an order with a location and a stat to all selected droids. add = true queues the order. */
void orderDroidStatsLocDirAdd(DROID *psDroid, DROID_ORDER order, STRUCTURE_STATS *psStats, UDWORD x, UDWORD y, uint16_t direction, bool add = true);

/** \brief Sends an order with two a locations and a stat to all selected droids. add = true queues the order. */
void orderSelectedStatsTwoLocDir(UDWORD player, DROID_ORDER order, STRUCTURE_STATS *psStats, UDWORD x1, UDWORD y1, UDWORD x2, UDWORD y2, uint16_t direction, bool add);

/** \brief Sees if a droid supports a given secondary order. */
bool secondarySupported(const DROID *psDroid, SECONDARY_ORDER sec);

/** \brief Gets the state of a secondary order, return false if unsupported. */
SECONDARY_STATE secondaryGetState(const DROID *psDroid, SECONDARY_ORDER sec, QUEUE_MODE mode = ModeImmediate);

/** \brief Sets the state of a secondary order, return false if failed. */
bool secondarySetState(DROID *psDroid, SECONDARY_ORDER sec, SECONDARY_STATE State, QUEUE_MODE mode = ModeQueue);

/** \brief Checks the damage level of a droid against it's secondary state. */
void secondaryCheckDamageLevel(DROID *psDroid);

/** \brief Makes all the members of a numeric group to have the same secondary states. */
void secondarySetAverageGroupState(UDWORD player, UDWORD group);

/** \brief Gets the name of an order. */
const char *getDroidOrderName(DROID_ORDER order);
const char *getDroidOrderKey(DROID_ORDER order);

/** \brief Gets a player's transporter. */
DROID *FindATransporter(DROID const *embarkee);

/** \brief Sets the state of a secondary order for a factory. */
bool setFactoryState(STRUCTURE *psStruct, SECONDARY_ORDER sec, SECONDARY_STATE State);

/** \brief Gets the state of a secondary order for a Factory. */
bool getFactoryState(const STRUCTURE *psStruct, SECONDARY_ORDER sec, SECONDARY_STATE *pState);

/** \brief lasSat structure can select a target. */
void orderStructureObj(UDWORD player, BASE_OBJECT *psObj);

/** \brief Pops orders (including pending orders) from the order list. */
void orderDroidListEraseRange(DROID *psDroid, unsigned indexBegin, unsigned indexEnd);

/** \brief Clears all orders for the given target (including pending orders) from the order list. */
void orderClearTargetFromDroidList(DROID *psDroid, BASE_OBJECT *psTarget);

/** \brief Chooses an order from a location. */
DROID_ORDER chooseOrderLoc(DROID *psDroid, UDWORD x, UDWORD y, bool altOrder);

/** \brief Chooses an order from an object. */
DroidOrder chooseOrderObj(DROID *psDroid, BASE_OBJECT *psObj, bool altOrder);

#endif // __INCLUDED_SRC_ORDER_H__
