/**
 * @brief This removes an employee from the global list so that
 * he/she is no longer hireable.
 */
static void E_EmployeeDelete_f (void)
{
	/* Check syntax. */
	if (cgi->Cmd_Argc() < 2) {
		Com_Printf("Usage: %s <num>\n", cgi->Cmd_Argv(0));
		return;
	}

	/* num - menu index (line in text) */
	int num = employeeScrollPos + atoi(cgi->Cmd_Argv(1));

	Employee* employee = E_GetEmployeeByMenuIndex(num);
	/* empty slot selected */
	if (!employee)
		return;

	if (employee->isHired()) {
		if (!employee->unhire()) {
			cgi->UI_DisplayNotice(_("Could not fire employee"), 2000, "employees");
			Com_DPrintf(DEBUG_CLIENT, "Couldn't fire employee\n");
			return;
		}
	}
	E_DeleteEmployee(employee);
	cgi->Cbuf_AddText("employee_init %i\n", employeeCategory);

	num = std::max(0, num - 1);
	cgi->Cbuf_AddText("employee_select %i\n", num);
	cgi->Cbuf_AddText("hire_select %i\n", num);

	cgi->Cbuf_AddText("employee_update_count\n");
}
/**
 * @brief Callback for employee_hire command
 * @note a + as parameter indicates, that more than @c maxEmployeesPerPage are possible
 * @sa CL_AssignSoldier_f
 */
static void E_EmployeeHire_f (void)
{
	/* num - menu index (line in text), button - number of button */
	int num, button;
	const char *arg;
	Employee* employee;
	base_t *base = B_GetCurrentSelectedBase();

	if (!base)
		return;

	/* Check syntax. */
	if (cgi->Cmd_Argc() < 2) {
		Com_Printf("Usage: %s <+num>\n", cgi->Cmd_Argv(0));
		return;
	}

	arg = cgi->Cmd_Argv(1);

	/* check whether this is called with the text node click function
	 * with values from 0 - #available employees (bigger values than
	 * maxEmployeesPerPage) possible ... */
	if (arg[0] == '+') {
		num = atoi(arg + 1);
		button = num - employeeScrollPos;
	/* ... or with the hire pictures that are using only values from
	 * 0 - maxEmployeesPerPage */
	} else {
		button = atoi(cgi->Cmd_Argv(1));
		num = button + employeeScrollPos;
	}

	employee = E_GetEmployeeByMenuIndex(num);
	/* empty slot selected */
	if (!employee)
		return;

	if (employee->isHired()) {
		if (!employee->unhire()) {
			Com_DPrintf(DEBUG_CLIENT, "Couldn't fire employee\n");
			cgi->UI_DisplayNotice(_("Could not fire employee"), 2000, "employees");
		} else {
			cgi->UI_ExecuteConfunc("employeehire %i", button);
		}
	} else {
		if (!E_HireEmployee(base, employee)) {
			Com_DPrintf(DEBUG_CLIENT, "Couldn't hire employee\n");
			cgi->UI_DisplayNotice(_("Could not hire employee"), 2000, "employees");
			cgi->UI_ExecuteConfunc("employeehire %i", button);
		} else {
			cgi->UI_ExecuteConfunc("employeefire %i", button);
		}
	}
	E_EmployeeSelect(employee);

	E_UpdateGUICount_f();
}
/**
 * @brief Callback function that updates the character cvars when calling employee_select
 */
static void E_EmployeeSelect_f (void)
{
	/* Check syntax. */
	if (cgi->Cmd_Argc() < 2) {
		Com_Printf("Usage: %s <num>\n", cgi->Cmd_Argv(0));
		return;
	}

	const int num = atoi(cgi->Cmd_Argv(1));
	if (num < 0 || num >= employeesInCurrentList)
		return;

	E_EmployeeSelect(E_GetEmployeeByMenuIndex(num));
}
/**
 * @brief Will fill the list with employees
 * @note this is the init function in the employee hire menu
 */
static void E_EmployeeList_f (void)
{
	Employee* employee;
	int hiredEmployeeIdx;
	linkedList_t* employeeListName;
	base_t* base = B_GetCurrentSelectedBase();

	if (!base)
		return;

	if (cgi->Cmd_Argc() < 2) {
		Com_Printf("Usage: %s <category> <employeeid>\n", cgi->Cmd_Argv(0));
		return;
	}

	employeeCategory = atoi(cgi->Cmd_Argv(1));
	if (employeeCategory >= MAX_EMPL || employeeCategory < 0)
		employeeCategory = EMPL_SOLDIER;

	if (cgi->Cmd_Argc() == 3)
		hiredEmployeeIdx = atoi(cgi->Cmd_Argv(2));
	else
		hiredEmployeeIdx = -1;

	/* reset the employee count */
	employeesInCurrentList = 0;

	cgi->LIST_Delete(&employeeList);
	/* make sure, that we are using the linked list */
	cgi->UI_ResetData(TEXT_LIST);
	employeeListName = nullptr;

	E_Foreach(employeeCategory, e) {
		/* don't show employees of other bases */
		if (e->isHired() && !e->isHiredInBase(base))
			continue;
		/* don't show employees being transferred to other bases */
		if (e->transfer)
			continue;
		cgi->LIST_AddPointer(&employeeListName, e->chr.name);
		cgi->LIST_AddPointer(&employeeList, e);
		employeesInCurrentList++;
	}
	cgi->UI_RegisterLinkedListText(TEXT_LIST, employeeListName);

	/* If the list is empty OR we are in pilots/scientists/workers-mode: don't show the model&stats. */
	/** @note
	 * 0 == nothing is displayed
	 * 1 == all is displayed
	 * 2 == only stuff wanted for scientists/workers/pilots are displayed
	 */
	/** @todo replace magic numbers - use confuncs */
	if (employeesInCurrentList == 0) {
		cgi->Cvar_Set("mn_show_employee", "0");
	} else {
		if (employeeCategory == EMPL_SCIENTIST || employeeCategory == EMPL_WORKER)
			cgi->Cvar_Set("mn_show_employee", "3");
		else if (employeeCategory == EMPL_PILOT)
			cgi->Cvar_Set("mn_show_employee", "2");
		else
			cgi->Cvar_Set("mn_show_employee", "1");
	}
	/* Select the current employee if name was changed or first one. Use the direct string
	 * execution here - otherwise the employeeCategory might be out of sync */
	if (hiredEmployeeIdx < 0 || selectedEmployee == nullptr)
		employee = E_GetEmployeeByMenuIndex(0);
	else
		employee = selectedEmployee;

	E_EmployeeSelect(employee);

	/* update scroll */
	cgi->UI_ExecuteConfunc("hire_update_number %i", employeesInCurrentList);
	cgi->UI_ExecuteConfunc("employee_scroll 0");
}