#include "..\script_component.hpp"
#include "..\defines.hpp"
/*
 * Author: Alganthe, Dedmen, Brett Mayson, johnb43
 * Sort an arsenal panel.
 *
 * Arguments:
 * 0: Control <CONTROL>
 *
 * Return Value:
 * None
 *
 * Public: No
*/

params ["_control"];

// https://community.bistudio.com/wiki/toString, see comment
// However, using 55295 did not work as expected, 55291 was found by trial and error
#define HIGHEST_VALUE_CHAR 55291

// When filling the sorting panel, FUNC(sortPanel) is called twice, so ignore first call
if (GVAR(ignoreFirstSortPanelCall)) exitWith {
    GVAR(ignoreFirstSortPanelCall) = false;
};

private _display = ctrlParent _control;
private _rightSort = (ctrlIDC _control) in [IDC_sortRightTab, IDC_sortRightTabDirection];
private _right = _rightSort && {GVAR(currentLeftPanel) in [IDC_buttonUniform, IDC_buttonVest, IDC_buttonBackpack]};
private _sortCtrl = _display displayCtrl ([IDC_sortLeftTab, IDC_sortRightTab] select _rightSort);
private _sortDirectionCtrl = _display displayCtrl ([IDC_sortLeftTabDirection, IDC_sortRightTabDirection] select _rightSort);

private _cfgMagazines = configFile >> "CfgMagazines";
private _cfgFaces = configFile >> "CfgFaces";
private _cfgUnitInsignia = configFile >> "CfgUnitInsignia";
private _cfgUnitInsigniaCampaign = campaignConfigFile >> "CfgUnitInsignia";
private _cfgUnitInsigniaMission = missionConfigFile >> "CfgUnitInsignia";

if (_rightSort) then {
    [
        if (_right) then {
            _display displayCtrl IDC_rightTabContentListnBox
        } else {
            _display displayCtrl IDC_rightTabContent
        },
        switch (GVAR(currentRightPanel)) do {
            case IDC_buttonCurrentMag;
            case IDC_buttonCurrentMag2;
            case IDC_buttonThrow;
            case IDC_buttonPut;
            case IDC_buttonMag;
            case IDC_buttonMagALL: {_cfgMagazines};
            default {configFile >> "CfgWeapons"};
        },
        GVAR(sortListRightPanel) select (
            switch (GVAR(currentRightPanel)) do {
                case IDC_buttonOptic: { 0 };
                case IDC_buttonItemAcc: { 1 };
                case IDC_buttonMuzzle: { 2 };
                case IDC_buttonBipod: { 3 };
                case IDC_buttonCurrentMag;
                case IDC_buttonCurrentMag2;
                case IDC_buttonMag;
                case IDC_buttonMagALL: { 4 };
                case IDC_buttonThrow: { 5 };
                case IDC_buttonPut: { 6 };
                case IDC_buttonMisc: { 7 };
            }
        )
    ]
} else {
    [
        _display displayCtrl IDC_leftTabContent,
        switch (GVAR(currentLeftPanel)) do {
            case IDC_buttonBackpack: {configFile >> "CfgVehicles"};
            case IDC_buttonGoggles: {configFile >> "CfgGlasses"};
            case IDC_buttonFace: {_cfgFaces};
            case IDC_buttonVoice: {configFile >> "CfgVoice"};
            case IDC_buttonInsignia: {_cfgUnitInsignia};
            default {configFile >> "CfgWeapons"};
        },
        (GVAR(sortListLeftPanel) select ([
            IDC_buttonPrimaryWeapon,
            IDC_buttonHandgun,
            IDC_buttonSecondaryWeapon,
            IDC_buttonUniform,
            IDC_buttonVest,
            IDC_buttonBackpack,
            IDC_buttonHeadgear,
            IDC_buttonGoggles,
            IDC_buttonNVG,
            IDC_buttonBinoculars,
            IDC_buttonMap,
            IDC_buttonGPS,
            IDC_buttonRadio,
            IDC_buttonCompass,
            IDC_buttonWatch,
            IDC_buttonFace,
            IDC_buttonVoice,
            IDC_buttonInsignia
        ] find GVAR(currentLeftPanel)))
    ]
} params ["_panel", "_cfgClass", "_sorts"];

// Get sort & sort direction
private _sortName = _sortCtrl lbData (0 max lbCurSel _sortCtrl);
private _sortDirection = _sortDirectionCtrl lbValue (0 max lbCurSel _sortDirectionCtrl);
(_sorts select (0 max (_sorts findIf {(_x select 0) == _sortName}))) params ["", "_displayName", "_statement"];

// Update last sort & sort direction
missionNamespace setVariable [
    [QGVAR(lastSortLeft), QGVAR(lastSortRight)] select _rightSort,
    _displayName
];

missionNamespace setVariable [
    [QGVAR(lastSortDirectionLeft), QGVAR(lastSortDirectionRight)] select _rightSort,
    _sortDirection
];

// Get currently selected item
private _curSel = if (_right) then {
    lnbCurSelRow _panel
} else {
    lbCurSel _panel
};

private _selected = if (_right) then {
    _panel lnbData [_curSel, 0]
} else {
    _panel lbData _curSel
};

private _item = "";
private _quantity = "";
private _itemCfg = configNull;
private _value = "";
private _name = "";
private _fillerChar = toString [1];

private _magazineMiscItems = uiNamespace getVariable QGVAR(magazineMiscItems);
private _sortCache = uiNamespace getVariable QGVAR(sortCache);
private _faceCache = uiNamespace getVariable QGVAR(faceCache);
private _insigniaCache = uiNamespace getVariable QGVAR(insigniaCache);

private _countColumns = if (_right) then {
    count lnbGetColumnsPosition _panel
} else {
    0
};

private _for = if (_right) then {
    for "_i" from 0 to (lnbSize _panel select 0) - 1
} else {
    for "_i" from 0 to (lbSize _panel) - 1
};

_for do {
    // Get item
    _item = if (_right) then {
        _panel lnbData [_i, 0]
    } else {
        _panel lbData _i
    };

    // Check if entry is "Empty"
    if (!_right && {(_panel lbValue _i) == -1}) then {
        // Set to lowest/highest lexicographical value, so that "Empty" is always at the top
        _panel lbSetTextRight [_i, ["", toString [HIGHEST_VALUE_CHAR, HIGHEST_VALUE_CHAR, HIGHEST_VALUE_CHAR, HIGHEST_VALUE_CHAR, HIGHEST_VALUE_CHAR]] select (_sortDirection == ASCENDING)];

        continue;
    };

    // Get item's count
    _quantity = if (_right) then {
        parseNumber (_panel lnbText [_i, 2])
    } else {
        0
    };

    // "Misc. items" magazines (e.g. spare barrels, intel, photos)
    if (_item in _magazineMiscItems) then {
        _cfgClass = _cfgMagazines;
    };

    // Check item's config
    _itemCfg = if !(_cfgClass in [_cfgFaces, _cfgUnitInsignia]) then {
        _cfgClass >> _item
    } else {
        // If insignia, check for correct config: First mission, then campaign and finally regular config
        if (_cfgClass == _cfgUnitInsignia) then {
            _itemCfg = _cfgUnitInsigniaMission >> _item;

            if (isNull _itemCfg) then {
                _itemCfg = _cfgUnitInsigniaCampaign >> _item;
            };

            if (isNull _itemCfg) then {
                _itemCfg = _cfgUnitInsignia >> _item;
            };

            _itemCfg
        } else {
            // If face, check correct category
            _cfgClass >> (_faceCache getOrDefault [_item, []]) param [2, "Man_A3"] >> _item
        };
    };

    // Some items may not belong to the config class for the panel (e.g. misc. items panel can have unique items)
    if (isNull _itemCfg) then {
        _itemCfg = _item call CBA_fnc_getItemConfig;
    };

    // Value can be any type
    _value = _sortCache getOrDefaultCall [format ["%1_%2_%3", _sortName, _item, _quantity], {
        private _value = [_itemCfg, _item, _quantity] call _statement;

        // If number, convert to string (keep 2 decimal after comma; Needed for correct weight sorting)
        if (_value isEqualType 0) then {
            _value = [_value, 8, 2] call CBA_fnc_formatNumber;
        };

        // If empty string, add alphabetically small char at beginning to make it sort correctly
        if (_value isEqualTo "") then {
            _value = "_";
        };

        _value
    }, true];

    // Set the right text temporarily, so it can be used for sorting
    if (_right) then {
        // Use value, display name and classname to sort, which means a fixed alphabetical order is guaranteed
        // Filler char has lowest lexicographical value possible
        _panel lnbSetTextRight [[_i, 1], format ["%1%2%4%3", _value, _panel lnbText [_i, 1], _item, _fillerChar]];
    } else {
        if (_item != "") then {
            // Use value, display name and classname to sort, which means a fixed alphabetical order is guaranteed
            // Filler char has lowest lexicographical value possible
            _panel lbSetTextRight [_i, format ["%1%2%4%3", _value, _panel lbText _i, _item, _fillerChar]];
        };
    };
};

// Sort alphabetically, find the previously selected item and select it again
if (_right) then {
    [_panel, 1] lnbSortBy ["TEXT", _sortDirection == ASCENDING, false, true, false];

    _for do {
        // Remove sorting text, as it blocks the item name otherwise
        _panel lnbSetTextRight [[_i, 1], ""];

        if (_curSel != -1 && {(_panel lnbData [_i, 0]) == _selected}) then {
            _panel lnbSetCurSelRow _i;

            // To avoid unnecessary checks after previsouly selected item was found
            _curSel = -1;
        };
    };
} else {
    _panel lbSortBy ["TEXT", _sortDirection == ASCENDING, false, true, false];

    _for do {
        _item = _panel lbData _i;

        // Check if valid item (problems can be caused when searching)
        if (_item != "") then {
            // Remove sorting text, as it blocks the item name otherwise
            _panel lbSetTextRight [_i, ""];
        };

        if (_curSel != -1 && {_item == _selected}) then {
            _panel lbSetCurSel _i;

            // To avoid unnecessary checks after previsouly selected item was found
            _curSel = -1;
        };
    };
};