/**
 * @brief Show item description in bdef menu
 * @note it handles items in both slots and storage
 */
static void BDEF_SelectItem_f (void)
{
	aircraftSlot_t* slot;
	installation_t* installation = INS_GetCurrentSelectedInstallation();
	base_t* base = B_GetCurrentSelectedBase();
	aircraftItemType_t bdefType;
	int slotIDX;
	int itemIDX;

	if (cgi->Cmd_Argc() < 4) {
		Com_Printf("Usage: %s <type> <slotIDX> <itemIDX>\n", cgi->Cmd_Argv(0));
		return;
	}

	bdefType = BDEF_GetItemTypeFromID(cgi->Cmd_Argv(1));
	slotIDX = atoi(cgi->Cmd_Argv(2));
	itemIDX = atoi(cgi->Cmd_Argv(3));

	if (bdefType == MAX_ACITEMS) {
		Com_Printf("BDEF_AddItem_f: Invalid defence type.\n");
		return;
	}

	if (slotIDX >= 0) {
		const objDef_t* item;
		slot = (installation) ? BDEF_GetInstallationSlotByIDX(installation, bdefType, slotIDX) : BDEF_GetBaseSlotByIDX(base, bdefType, slotIDX);
		item = (slot) ? ( (slot->nextItem) ? slot->nextItem : slot->item ) : nullptr;
		UP_AircraftItemDescription(item);
	} else if (itemIDX >= 0) {
		technology_t** list;
		technology_t* itemTech = nullptr;
		int i = 0;

		slot = (installation) ? BDEF_GetInstallationSlotByIDX(installation, bdefType, 0) : BDEF_GetBaseSlotByIDX(base, bdefType, 0);
		list = AII_GetCraftitemTechsByType(bdefType);
		while (*list && i <= itemIDX) {
			if (AIM_SelectableCraftItem(slot, *list)) {
				itemTech = *list;
				i++;
				break;
			}
			list++;
		}
		UP_AircraftItemDescription((itemTech) ? INVSH_GetItemByIDSilent(itemTech->provides) : nullptr);
	} else {
		Com_Printf("BDEF_AddItem_f: Invalid item-space.\n");
	}
}
/**
 * @brief Update the list of item you can choose
 * @param[in] slot Pointer to aircraftSlot where items can be equiped
 */
static void BDEF_UpdateAircraftItemList (const aircraftSlot_t* slot)
{
	linkedList_t* itemList = nullptr;
	technology_t** list;

	assert(slot);

	/* Add all items corresponding to airequipID to list */
	list = AII_GetCraftitemTechsByType(slot->type);

	/* Copy only those which are researched to buffer */
	while (*list) {
		if (AIM_SelectableCraftItem(slot, *list))
			cgi->LIST_AddString(&itemList, _((*list)->name));
		list++;
	}

	/* copy buffer to mn.menuText to display it on screen */
	cgi->UI_RegisterLinkedListText(TEXT_LIST, itemList);
}
/**
 * @brief Update the list of item you can choose
 * @param[in] slot Pointer to aircraftSlot where items can be equiped
 */
static void AIM_UpdateAircraftItemList (const aircraftSlot_t *slot)
{
	linkedList_t *amountList = NULL;
	technology_t **techList;
	technology_t **currentTech;
	const base_t *base = slot->aircraft->homebase;
	int count = 0;
	uiNode_t *AIM_items = NULL;

	/* Add all items corresponding to airequipID to list */
	techList = AII_GetCraftitemTechsByType(airequipID);

	/* Count only those which are researched to buffer */
	currentTech = techList;
	while (*currentTech) {
		if (AIM_CrafttypeFilter(base, airequipID, *currentTech))
			count++;
		currentTech++;
	}

	/* List only those which are researched to buffer */
	currentTech = techList;
	while (*currentTech) {
		if (AIM_CrafttypeFilter(base, airequipID, *currentTech)) {
			uiNode_t *option;
			const objDef_t *item = INVSH_GetItemByID((*currentTech)->provides);
			const int amount = B_ItemInBase(item, base);

			LIST_AddString(&amountList, va("%d", amount));
			option = cgi->UI_AddOption(&AIM_items, (*currentTech)->name, _((*currentTech)->name), va("%d", (*currentTech)->idx));
			if (!AIM_SelectableCraftItem(slot, *currentTech))
				option->disabled = true;
		}
		currentTech++;
	}

	cgi->UI_RegisterOption(TEXT_LIST, AIM_items);
	cgi->UI_RegisterLinkedListText(TEXT_LIST2, amountList);
}
/**
 * @brief add item to a base defence slot (installation too)
 */
static void BDEF_AddItem_f (void)
{
	aircraftSlot_t* slot;
	installation_t* installation = INS_GetCurrentSelectedInstallation();
	base_t* base = B_GetCurrentSelectedBase();
	technology_t** list;
	technology_t* itemTech = nullptr;
	aircraftItemType_t bdefType;
	int slotIDX;

	if ((!base && !installation) || (base && installation)) {
		Com_Printf("Exiting early base and installation both true or both false\n");
		return;
	}

	if (cgi->Cmd_Argc() < 3) {
		Com_Printf("Usage: %s <type> <slotIDX>\n", cgi->Cmd_Argv(0));
		return;
	}

	bdefType = BDEF_GetItemTypeFromID(cgi->Cmd_Argv(1));
	slotIDX = atoi(cgi->Cmd_Argv(2));

	if (bdefType == MAX_ACITEMS) {
		Com_Printf("BDEF_AddItem_f: Invalid defence type.\n");
		return;
	}

	if (slotIDX < 0) {
		return;
	} else {
		int maxWeapon;
		if (base)
			maxWeapon = (bdefType == AC_ITEM_BASE_MISSILE) ? base->numActiveBatteries : base->numActiveLasers;
		else
			maxWeapon = installation->numBatteries;
		if (slotIDX >= maxWeapon)
			return;
	}

	slot = (installation) ? BDEF_GetInstallationSlotByIDX(installation, bdefType, slotIDX) : BDEF_GetBaseSlotByIDX(base, bdefType, slotIDX);

	if (!slot) {
		Com_Printf("BDEF_AddItem_f: Invalid slot.\n");
		return;
	}

	list = AII_GetCraftitemTechsByType(bdefType);
	while (*list) {
		if (AIM_SelectableCraftItem(slot, *list)) {
			itemTech = *list;
			break;
		}
		list++;
	}

	if (!itemTech)
		return;

	if (!slot->nextItem) {
		/* we add the weapon, shield, item, or base defence if slot is free or the installation of
		 * current item just began */
		if (!slot->item || (slot->item && slot->installationTime == slot->item->craftitem.installationTime)) {
			AII_RemoveItemFromSlot(base, slot, false);
			AII_AddItemToSlot(base, itemTech, slot, false); /* Aircraft stats are updated below */
			AII_AutoAddAmmo(slot);
		} else if (slot->item == INVSH_GetItemByID(itemTech->provides)) {
			/* the added item is the same than the one in current slot */
			if (slot->installationTime == -slot->item->craftitem.installationTime) {
				/* player changed his mind: he just want to re-add the item he just removed */
				slot->installationTime = 0;
			} else if (!slot->installationTime) {
				/* player try to add a weapon he already have: just skip */
			}
		} else {
			/* We start removing current item in slot, and the selected item will be installed afterwards */
			slot->installationTime = -slot->item->craftitem.installationTime;
			AII_AddItemToSlot(base, itemTech, slot, true);
			AII_AutoAddAmmo(slot);
		}
	} else {
		/* remove weapon and ammo of next item */
		AII_RemoveItemFromSlot(base, slot, false);
		AII_AddItemToSlot(base, itemTech, slot, true);
		AII_AutoAddAmmo(slot);
	}

	/* Reinit menu */
	cgi->Cmd_ExecuteString("basedef_updatemenu %s", BDEF_GetIDFromItemType(slot->type));
}