/**
 * Moves the given number of items (selected) to the base.
 */
void CraftEquipmentState::moveLeft(int change)
{
	Craft *c = _base->getCrafts()->at(_craft);
	RuleItem *item = _game->getRuleset()->getItem(_items[_sel]);
	int cQty = 0;
	if (item->isFixed()) cQty = c->getVehicleCount(_items[_sel]);
	else cQty = c->getItems()->getItem(_items[_sel]);
	if (0 >= change || 0 >= cQty) return;
	change = std::min(cQty, change);
	// Convert vehicle to item
	if (item->isFixed())
	{
		if(item->getClipSize() != -1)
		{
			// First we remove all vehicles because we want to redistribute the ammo
			RuleItem *ammo = _game->getRuleset()->getItem(item->getCompatibleAmmo()->front());
			for (std::vector<Vehicle*>::iterator i = c->getVehicles()->begin(); i != c->getVehicles()->end(); )
			{
				if ((*i)->getRules() == item)
				{
					_base->getItems()->addItem(ammo->getType(), (*i)->getAmmo());
					delete (*i);
					c->getVehicles()->erase(i);
					i = c->getVehicles()->begin(); // Since we erased the current iterator, we have to start over (to avoid a crash)
				}
				else ++i;
			}
			_base->getItems()->addItem(_items[_sel], cQty);
			// And now reAdd the count we want to keep in the craft (and redistribute the ammo among them)
			if (cQty > change) moveRight(cQty - change);
		}
		else
		{
			_base->getItems()->addItem(_items[_sel], change);
			for (std::vector<Vehicle*>::iterator i = c->getVehicles()->begin(); i != c->getVehicles()->end(); )
			{
				if ((*i)->getRules() == item)
				{
					delete (*i);
					c->getVehicles()->erase(i);
					if (0 >= --change) break;
					i = c->getVehicles()->begin(); // Since we erased the current iterator, we have to start over (to avoid a crash)
				}
				else ++i;
			}
		}
	}
	else
	{
		c->getItems()->removeItem(_items[_sel], change);
		_base->getItems()->addItem(_items[_sel], change);
	}
	updateQuantity();
}
/**
 * Moves all the items to the base on right-click.
 * @param action Pointer to an action.
 */
void CraftEquipmentState::lstEquipmentLeftArrowClick(Action *action)
{
	if (action->getDetails()->button.button == SDL_BUTTON_RIGHT)
	{
		Craft *c = _base->getCrafts()->at(_craft);
		RuleItem *item = _game->getRuleset()->getItem(_items[_sel]);
		int cQty = 0;
		if (item->isFixed())
		{
			cQty = c->getVehicleCount(_items[_sel]);
			if (cQty > 0)
			{
				while (cQty > 0)
				{
					RuleItem *ammo = _game->getRuleset()->getItem(item->getCompatibleAmmo()->front());
					for (std::vector<Vehicle*>::iterator i = c->getVehicles()->begin(); i != c->getVehicles()->end(); ++i)
					{
						if ((*i)->getRules() == item)
						{
							_base->getItems()->addItem(ammo->getType(), (*i)->getAmmo());
							delete (*i);
							c->getVehicles()->erase(i);
							break;
						}
					}
					_base->getItems()->addItem(_items[_sel]);
					cQty = c->getVehicleCount(_items[_sel]);
				}
				updateQuantity();
			}
		}
		else
		{
			cQty = c->getItems()->getItem(_items[_sel]);
			if (cQty > 0)
			{
				_base->getItems()->addItem(_items[_sel], cQty);
				c->getItems()->removeItem(_items[_sel], cQty);
				updateQuantity();
			}
		}
	}
}
/**
 * Moves the selected item to the base.
 */
void CraftEquipmentState::moveLeft()
{
	Craft *c = _base->getCrafts()->at(_craft);
	RuleItem *item = _game->getRuleset()->getItem(_items[_sel]);
	int cQty = 0;
	if (item->isFixed())
	{
		cQty = c->getVehicleCount(_items[_sel]);
	}
	else
	{
		cQty = c->getItems()->getItem(_items[_sel]);
	}
	if (cQty > 0)
	{
		RuleItem *item = _game->getRuleset()->getItem(_items[_sel]);
		// Convert vehicle to item
		if (item->isFixed())
		{
			RuleItem *ammo = _game->getRuleset()->getItem(item->getCompatibleAmmo()->front());
			for (std::vector<Vehicle*>::iterator i = c->getVehicles()->begin(); i != c->getVehicles()->end(); ++i)
			{
				if ((*i)->getRules() == item)
				{
					_base->getItems()->addItem(ammo->getType(), (*i)->getAmmo());
					delete (*i);
					c->getVehicles()->erase(i);
					break;
				}
			}
			_base->getItems()->addItem(_items[_sel]);
		}
		else
		{
			_base->getItems()->addItem(_items[_sel]);
			c->getItems()->removeItem(_items[_sel]);
		}
		updateQuantity();
	}
}
/**
 * Moves all the items (as much as possible) to the craft on right-click.
 * @param action Pointer to an action.
 */
void CraftEquipmentState::lstEquipmentRightArrowClick(Action *action)
{
	if (action->getDetails()->button.button == SDL_BUTTON_RIGHT)
	{
		Craft *c = _base->getCrafts()->at(_craft);
		RuleItem *item = _game->getRuleset()->getItem(_items[_sel]);
		int bqty = _base->getItems()->getItem(_items[_sel]);
		if (bqty > 0)
		{
			// Do we need to convert item to vehicle?
			if (item->isFixed())
			{
				// Check if there's enough room
				int room = std::min(c->getRules()->getVehicles() - c->getNumVehicles(), c->getSpaceAvailable() / 4);
				if (room > 0)
				{
					RuleItem *ammo = _game->getRuleset()->getItem(item->getCompatibleAmmo()->front());
					int baqty = _base->getItems()->getItem(ammo->getType());
					int vehiclesCount = std::min(std::min(bqty, room), baqty);
					if (vehiclesCount > 0)
					{
						int newAmmoPerVehicle = std::min(baqty / vehiclesCount, ammo->getClipSize());;
						int remainder = baqty - (vehiclesCount * newAmmoPerVehicle);
						if (ammo->getClipSize() == newAmmoPerVehicle) remainder = 0;
						int newAmmo;
						for (int i=0; i < vehiclesCount; ++i)
						{
							newAmmo = newAmmoPerVehicle;
							if (i<remainder) ++newAmmo;
							c->getVehicles()->push_back(new Vehicle(item, newAmmo));
							_base->getItems()->removeItem(ammo->getType(), newAmmo);
							_base->getItems()->removeItem(_items[_sel]);
						}
					}
				}
			}
			else
			{
				_base->getItems()->removeItem(_items[_sel],bqty);
				c->getItems()->addItem(_items[_sel],bqty);
			}
			updateQuantity();
		}
	}
}
/**
 * Moves the selected item to the craft.
 */
void CraftEquipmentState::moveRight()
{
	Craft *c = _base->getCrafts()->at(_craft);
	RuleItem *item = _game->getRuleset()->getItem(_items[_sel]);
	if (_base->getItems()->getItem(_items[_sel]) > 0)
	{
		// Convert item to vehicle
		if (item->isFixed())
		{
			// Check if there's enough room
			if (c->getNumVehicles() < c->getRules()->getVehicles() && c->getSpaceAvailable() >= 4)
			{
				RuleItem *ammo = _game->getRuleset()->getItem(item->getCompatibleAmmo()->front());
				int qty = _base->getItems()->getItem(ammo->getType());
				if (qty == 0)
				{
					std::wstringstream ss;
					ss << _game->getLanguage()->getString("STR_NOT_ENOUGH");
					ss << _game->getLanguage()->getString(ammo->getType());
					ss << _game->getLanguage()->getString("STR_TO_ARM_HWP");
					_game->pushState(new ErrorMessageState(_game, ss.str(), Palette::blockOffset(15)+1, "BACK04.SCR", 2));
					_timerRight->stop();
				}
				else
				{
					int newAmmo = std::min(qty, ammo->getClipSize());
					c->getVehicles()->push_back(new Vehicle(item, newAmmo));
					_base->getItems()->removeItem(ammo->getType(), newAmmo);
					_base->getItems()->removeItem(_items[_sel]);
				}
			}
		}
		else
		{
			_base->getItems()->removeItem(_items[_sel]);
			c->getItems()->addItem(_items[_sel]);
		}
		updateQuantity();
	}
}
/**
 * Moves the given number of items (selected) to the craft.
 */
void CraftEquipmentState::moveRight(int change)
{
	Craft *c = _base->getCrafts()->at(_craft);
	RuleItem *item = _game->getRuleset()->getItem(_items[_sel]);
	int bqty = _base->getItems()->getItem(_items[_sel]);
	if (0 >= change || 0 >= bqty) return;
	change = std::min(bqty, change);
	// Do we need to convert item to vehicle?
	if (item->isFixed())
	{
		// Check if there's enough room
		int room = std::min(c->getRules()->getVehicles() - c->getNumVehicles(), c->getSpaceAvailable() / 4);
		if (room > 0)
		{
			change = std::min(room, change);
			if(item->getClipSize() != -1)
			{
				// We want to redistribute all the available ammo among the vehicles,
				// so first we note the total number of vehicles we want in the craft
				int oldVehiclesCount = c->getVehicleCount(_items[_sel]);
				int newVehiclesCount = oldVehiclesCount + change;
				// ...and we move back all of this vehicle-type to the base.
				if (0 < oldVehiclesCount) moveLeft(INT_MAX);
				// And now let's see if we can add the total number of vehicles.
				RuleItem *ammo = _game->getRuleset()->getItem(item->getCompatibleAmmo()->front());
				int baqty = _base->getItems()->getItem(ammo->getType()); // Ammo Quantity for this vehicle-type on the base
				int canBeAdded = std::min(newVehiclesCount, baqty);
				if (canBeAdded > 0)
				{
					int newAmmoPerVehicle = std::min(baqty / canBeAdded, ammo->getClipSize());;
					int remainder = 0;
					if (ammo->getClipSize() > newAmmoPerVehicle) remainder = baqty - (canBeAdded * newAmmoPerVehicle);
					int newAmmo;
					for (int i=0; i < canBeAdded; ++i)
					{
						newAmmo = newAmmoPerVehicle;
						if (i<remainder) ++newAmmo;
						c->getVehicles()->push_back(new Vehicle(item, newAmmo));
						_base->getItems()->removeItem(ammo->getType(), newAmmo);
						_base->getItems()->removeItem(_items[_sel]);
					}
				}
				if (oldVehiclesCount >= canBeAdded)
				{
					// So we haven't managed to increase the count of vehicles because of the ammo
					_timerRight->stop();
					LocalizedText msg(tr("STR_NOT_ENOUGH_ammotype_TO_ARM_HWP").arg(tr(ammo->getType())));
					_game->pushState(new ErrorMessageState(_game, msg, Palette::blockOffset(15)+1, "BACK04.SCR", 2));
				}
			}
			else
				for (int i=0; i < change; ++i)
				{
					c->getVehicles()->push_back(new Vehicle(item, 255));
					_base->getItems()->removeItem(_items[_sel]);
				}
		}
	}
	else
	{
		_base->getItems()->removeItem(_items[_sel],change);
		c->getItems()->addItem(_items[_sel],change);
	}
	updateQuantity();
}
/**
 * Sells the selected items.
 * @param action Pointer to an action.
 */
void SellState::btnOkClick(Action *)
{
	_game->getSavedGame()->setFunds(_game->getSavedGame()->getFunds() + _total);
	for (size_t i = 0; i < _qtys.size(); ++i)
	{
		if (_qtys[i] > 0)
		{
			switch (getType(i))
			{
			case SELL_SOLDIER:
				for (std::vector<Soldier*>::iterator s = _base->getSoldiers()->begin(); s != _base->getSoldiers()->end(); ++s)
				{
					if (*s == _soldiers[i])
					{
						if ((*s)->getArmor()->getStoreItem() != "STR_NONE")
						{
							_base->getItems()->addItem((*s)->getArmor()->getStoreItem());
						}
						_base->getSoldiers()->erase(s);
						break;
					}
				}
				delete _soldiers[i];
				break;

			case SELL_CRAFT:
				{
				Craft *craft = _crafts[getCraftIndex(i)];

				// Remove weapons from craft
				for (std::vector<CraftWeapon*>::iterator w = craft->getWeapons()->begin(); w != craft->getWeapons()->end(); ++w)
				{
					if ((*w) != 0)
					{
						_base->getItems()->addItem((*w)->getRules()->getLauncherItem());
						_base->getItems()->addItem((*w)->getRules()->getClipItem(), (*w)->getClipsLoaded(_game->getRuleset()));
					}
				}

				// Remove items from craft
				for (std::map<std::string, int>::iterator it = craft->getItems()->getContents()->begin(); it != craft->getItems()->getContents()->end(); ++it)
				{
					_base->getItems()->addItem(it->first, it->second);
				}

				// Remove vehicles from craft
				for (std::vector<Vehicle*>::iterator v = craft->getVehicles()->begin(); v != craft->getVehicles()->end(); ++v)
				{
					_base->getItems()->addItem((*v)->getRules()->getType());
					_base->getItems()->addItem((*v)->getRules()->getCompatibleAmmo()->front(), (*v)->getAmmo());
				}

				// Remove soldiers from craft
				for (std::vector<Soldier*>::iterator s = _base->getSoldiers()->begin(); s != _base->getSoldiers()->end(); ++s)
				{
					if ((*s)->getCraft() == craft)
					{
						(*s)->setCraft(0);
					}
				}

				// Clear Hangar
				for (std::vector<BaseFacility*>::iterator f = _base->getFacilities()->begin(); f != _base->getFacilities()->end(); ++f)
				{
					if ((*f)->getCraft() == craft)
					{
						(*f)->setCraft(0);
						break;
					}
				}

				// Remove craft
				for (std::vector<Craft*>::iterator c = _base->getCrafts()->begin(); c != _base->getCrafts()->end(); ++c)
				{
					if (*c == craft)
					{
						_base->getCrafts()->erase(c);
						break;
					}
				}
				delete craft;
				}
				break;

			case SELL_SCIENTIST:
				_base->setScientists(_base->getScientists() - _qtys[i]);
				break;

			case SELL_ENGINEER:
				_base->setEngineers(_base->getEngineers() - _qtys[i]);
				break;

			case SELL_ITEM:
				if (_base->getItems()->getItem(_items[getItemIndex(i)]) < _qtys[i])
				{
					const std::string itemName = _items[getItemIndex(i)];
					int toRemove = _qtys[i] - _base->getItems()->getItem(itemName);

					// remove all of said items from base
					_base->getItems()->removeItem(itemName, INT_MAX);

					// if we still need to remove any, remove them from the crafts first, and keep a running tally
					for (std::vector<Craft*>::iterator j = _base->getCrafts()->begin(); j != _base->getCrafts()->end() && toRemove; ++j)
					{
						if ((*j)->getItems()->getItem(itemName) < toRemove)
						{
							toRemove -= (*j)->getItems()->getItem(itemName);
							(*j)->getItems()->removeItem(itemName, INT_MAX);
						}
						else
						{
							(*j)->getItems()->removeItem(itemName, toRemove);
							toRemove = 0;
						}
					}

					// if there are STILL any left to remove, take them from the transfers, and if necessary, delete it.
					for (std::vector<Transfer*>::iterator j = _base->getTransfers()->begin(); j != _base->getTransfers()->end() && toRemove;)
					{
						if ((*j)->getItems() == itemName)
						{
							if ((*j)->getQuantity() <= toRemove)
							{
								toRemove -= (*j)->getQuantity();
								delete *j;
								j = _base->getTransfers()->erase(j);
							}
							else
							{
								(*j)->setItems((*j)->getItems(), (*j)->getQuantity() - toRemove);
								toRemove = 0;
							}
						}
						else
						{
							++j;
						}
					}
				}
				else
				{
					_base->getItems()->removeItem(_items[getItemIndex(i)], _qtys[i]);
				}
			}
		}
	}
	_game->popState();
}
/**
 * Moves the given number of items (selected) to the craft.
 * @param change Item difference.
 */
void CraftEquipmentState::moveRightByValue(int change)
{
	Craft *c = _base->getCrafts()->at(_craft);
	RuleItem *item = _game->getMod()->getItem(_items[_sel]);
	int bqty = _base->getStorageItems()->getItem(_items[_sel]);
	if (_game->getSavedGame()->getMonthsPassed() == -1)
	{
		if (change == INT_MAX)
		{
			change = 10;
		}
		bqty = change;
	}
	if (0 >= change || 0 >= bqty) return;
	change = std::min(bqty, change);
	// Do we need to convert item to vehicle?
	if (item->isFixed())
	{
		int size = 4;
		if (_game->getMod()->getUnit(item->getType()))
		{
			size = _game->getMod()->getArmor(_game->getMod()->getUnit(item->getType())->getArmor())->getSize();
			size *= size;
		}
		// Check if there's enough room
		int room = std::min(c->getRules()->getVehicles() - c->getNumVehicles(), c->getSpaceAvailable() / size);
		if (room > 0)
		{
			change = std::min(room, change);
			if (!item->getCompatibleAmmo()->empty())
			{
				// And now let's see if we can add the total number of vehicles.
				RuleItem *ammo = _game->getMod()->getItem(item->getCompatibleAmmo()->front());
				int ammoPerVehicle, clipSize;
				if (ammo->getClipSize() > 0 && item->getClipSize() > 0)
				{
					clipSize = item->getClipSize();
					ammoPerVehicle = clipSize / ammo->getClipSize();
				}
				else
				{
					clipSize = ammo->getClipSize();
					ammoPerVehicle = clipSize;
				}

				int baseQty = _base->getStorageItems()->getItem(ammo->getType()) / ammoPerVehicle;
				if (_game->getSavedGame()->getMonthsPassed() == -1)
					baseQty = 1;
				int canBeAdded = std::min(change, baseQty);
				if (canBeAdded > 0)
				{
					for (int i=0; i < canBeAdded; ++i)
					{
						if (_game->getSavedGame()->getMonthsPassed() != -1)
						{
							_base->getStorageItems()->removeItem(ammo->getType(), ammoPerVehicle);
							_base->getStorageItems()->removeItem(_items[_sel]);
						}
						c->getVehicles()->push_back(new Vehicle(item, clipSize, size));
					}
				}
				else
				{
					// So we haven't managed to increase the count of vehicles because of the ammo
					_timerRight->stop();
					LocalizedText msg(tr("STR_NOT_ENOUGH_AMMO_TO_ARM_HWP").arg(tr(ammo->getType())));
					_game->pushState(new ErrorMessageState(msg, _palette, _game->getMod()->getInterface("craftEquipment")->getElement("errorMessage")->color, "BACK04.SCR", _game->getMod()->getInterface("craftEquipment")->getElement("errorPalette")->color));
				}
			}
			else
				for (int i=0; i < change; ++i)
				{
					c->getVehicles()->push_back(new Vehicle(item, item->getClipSize(), size));
					if (_game->getSavedGame()->getMonthsPassed() != -1)
					{
						_base->getStorageItems()->removeItem(_items[_sel]);
					}
				}
		}
	}
	else
	{
		if (c->getRules()->getMaxItems() > 0 && _totalItems + change > c->getRules()->getMaxItems())
		{
			_timerRight->stop();
			LocalizedText msg(tr("STR_NO_MORE_EQUIPMENT_ALLOWED", c->getRules()->getMaxItems()));
			_game->pushState(new ErrorMessageState(msg, _palette, _game->getMod()->getInterface("craftEquipment")->getElement("errorMessage")->color, "BACK04.SCR", _game->getMod()->getInterface("craftEquipment")->getElement("errorPalette")->color));
			change = c->getRules()->getMaxItems() - _totalItems;
		}
		c->getItems()->addItem(_items[_sel],change);
		_totalItems += change;
		if (_game->getSavedGame()->getMonthsPassed() > -1)
		{
			_base->getStorageItems()->removeItem(_items[_sel],change);
		}
	}
	updateQuantity();
}
/**
 * Moves the given number of items (selected) to the base.
 * @param change Item difference.
 */
void CraftEquipmentState::moveLeftByValue(int change)
{
	Craft *c = _base->getCrafts()->at(_craft);
	RuleItem *item = _game->getMod()->getItem(_items[_sel]);
	int cQty = 0;
	if (item->isFixed()) cQty = c->getVehicleCount(_items[_sel]);
	else cQty = c->getItems()->getItem(_items[_sel]);
	if (change <= 0 || cQty <= 0) return;
	change = std::min(cQty, change);
	// Convert vehicle to item
	if (item->isFixed())
	{
		if (!item->getCompatibleAmmo()->empty())
		{
			// First we remove all vehicles because we want to redistribute the ammo
			RuleItem *ammo = _game->getMod()->getItem(item->getCompatibleAmmo()->front());
			for (std::vector<Vehicle*>::iterator i = c->getVehicles()->begin(); i != c->getVehicles()->end(); )
			{
				if ((*i)->getRules() == item)
				{
					_base->getStorageItems()->addItem(ammo->getType(), (*i)->getAmmo());
					delete (*i);
					i = c->getVehicles()->erase(i);
				}
				else ++i;
			}
			if (_game->getSavedGame()->getMonthsPassed() != -1)
			{
				_base->getStorageItems()->addItem(_items[_sel], cQty);
			}
			// And now reAdd the count we want to keep in the craft (and redistribute the ammo among them)
			if (cQty > change) moveRightByValue(cQty - change);
		}
		else
		{
			if (_game->getSavedGame()->getMonthsPassed() != -1)
			{
				_base->getStorageItems()->addItem(_items[_sel], change);
			}
			for (std::vector<Vehicle*>::iterator i = c->getVehicles()->begin(); i != c->getVehicles()->end(); )
			{
				if ((*i)->getRules() == item)
				{
					delete (*i);
					i = c->getVehicles()->erase(i);
					if (0 >= --change) break;
				}
				else ++i;
			}
		}
	}
	else
	{
		c->getItems()->removeItem(_items[_sel], change);
		_totalItems -= change;
		if (_game->getSavedGame()->getMonthsPassed() > -1)
		{
			_base->getStorageItems()->addItem(_items[_sel], change);
		}
	}
	updateQuantity();
}