#include "script_component.hpp"
/*
 * Author: jaynus, PabstMirror
 * Main loop, handles scaning for targets and drawing the javelin optic
 *
 * Arguments:
 * 0: Last run frame <NUMBER>
 * 0: Current target (what we locked last run) <OBJECT>
 * 0: Lock start time (cba mission time) <NUMBER>
 * 0: Next sound play time (ticktime) <NUMBER>
 * 0: Next target scan (ticktime) <NUMBER>
 *
 * Return Value:
 * None
 *
 * Example:
 * [] call ace_javelin_fnc_onOpticDraw
 *
 * Public: No
 */

// TRACE_1("onOpticDraw",diag_frameno);

#define __TRACKINTERVAL 0       // how frequent the ui update should be.
#define __SCANNTERVAL 0.05      // how frequent the target scan check should be.
#define __LOCKONTIME 3          // Lock on won't occur sooner

// Pull the arguments
params ["_lastRunFrame", "_currentTarget", "_lockStartTime", "_soundNextPlayTime", "_fireDisabledEH", "_nextTargetScan"];

// Get shooter info
private _currentShooter = if (ACE_player call CBA_fnc_canUseWeapon) then {ACE_player} else {vehicle ACE_player};
private _currentWeapon = currentWeapon _currentShooter;
private _currentMagazine = currentMagazine _currentShooter;

// Get weapon / ammo configs
private _ammoCount = _currentShooter ammo _currentWeapon;
private _weaponConfig = configProperties [configFile >> "CfgWeapons" >> _currentWeapon, QUOTE(configName _x == QUOTE(QGVAR(enabled))), false];
private _ammoConfig = if (_currentMagazine != "") then {
    private _ammoType = getText (configFile >> "CfgMagazines" >> _currentMagazine >> "ammo");
    configProperties [(configFile >> "CfgAmmo" >> _ammoType), "(configName _x) == 'ace_missileguidance'", false];
} else {
    []
};

// Check if loaded and javelin enabled for wepaon and missile guidance enabled for loaded ammo
if ((_ammoCount == 0) || // No ammo loaded
        {(count _weaponConfig) < 1} || {(getNumber (_weaponConfig select 0)) != 1} || // Not enabled for weapon
        {(count _ammoConfig) < 1} || {(getNumber ((_ammoConfig select 0) >> "enabled")) != 1} // Not enabled for ammo
        ) exitWith {

    __JavelinIGUITargeting ctrlShow false;
    __JavelinIGUISeek ctrlSetTextColor __ColorGray;

    _fireDisabledEH = [_fireDisabledEH] call FUNC(enableFire);
    _this set [0, diag_frameno];
    _this set [4, _fireDisabledEH];

    // Fix weapon being in top-attack when loading AP magazine (https://feedback.bistudio.com/T171012)
    if ((_currentShooter == ACE_player) && {_currentMagazine == "Titan_AP"} && {currentWeaponMode ACE_player == "TopDown"}) then {
        {
            _x params ["_xIndex", "", "", "", "_xMode"];
            if (_xMode == "Single") exitWith {
                ACE_player action ["SwitchWeapon", _currentShooter, ACE_player, _xIndex];
                __JavelinIGUITop ctrlSetTextColor __ColorGray;
                __JavelinIGUIDir ctrlSetTextColor __ColorGreen;
                TRACE_2("fix top-attack for AP",weaponState _currentShooter,_x);
            };
        } forEach (ACE_player weaponsInfo [_currentWeapon, true]);
    };
};


// Bail on fast movement (keep it steady)
if ((velocity ACE_player) distance [0,0,0] > 0.75 && {cameraView == "GUNNER"} && {cameraOn == ACE_player}) exitWith {
    TRACE_1("exiting gunner because movement",velocity ACE_player);
    ACE_player switchCamera "INTERNAL";
    if (player != ACE_player) then {
        TRACE_2("Zeus, manually reseting RC after switchCamera",player,ACE_player);
        player remoteControl ACE_player;
    };
};

// Refresh the firemode (top/dir)
[] call FUNC(showFireMode);

// Get UI constants
private _offsetX = 0.5 * safeZoneW - safeZoneX - 0.5;
private _offsetY = 0.5 * safeZoneH - safeZoneY - 0.5;

private _newTarget = objNull;
if (GVAR(isLockKeyDown) && {cameraView == "GUNNER"} && {((currentVisionMode ACE_player) == 2) || {missionNamespace getVariable [QGVAR(ignoreVisionMode), false]}}) then {
    // Attempting to lock; getTarget can be  expensive so it's rate is limited
    if (diag_tickTime > _nextTargetScan) then {
        BEGIN_COUNTER(getTarget);
        _newTarget = [_currentTarget, 2500, 0.6] call FUNC(getTarget);
        END_COUNTER(getTarget);
        _nextTargetScan = diag_tickTime + __SCANNTERVAL;
    } else {
        _newTarget = _currentTarget;
    };

    // Show gate box
    private _boundsInput = if (_currentTarget isKindOf "CAManBase") then {
        [_currentTarget,[-0.5,-0.5,-0.25],[0,0,0]];
    } else {
        [_currentTarget,[-1,-1,-1],_currentTarget selectionPosition "zamerny"];
    };

    private _bpos = _boundsInput call EFUNC(common,worldToScreenBounds);

    private _lockTime = if (isNull _currentTarget) then {0} else {CBA_missionTime - _lockStartTime};
    private _minX = ((linearConversion [1, (__LOCKONTIME - 0.5), _lockTime, 0.5 - 0.075*safeZoneW, (_bpos select 0), true]) + _offsetX) max __ConstraintLeft;
    private _minY = ((linearConversion [1, (__LOCKONTIME - 0.5), _lockTime, 0.5 - 0.075*safeZoneH, (_bpos select 1), true]) + _offsetY) max __ConstraintTop;
    private _maxX = (((linearConversion [1, (__LOCKONTIME - 0.5), _lockTime, 0.5 + 0.075*safeZoneW, (_bpos select 2), true]) + _offsetX) min __ConstraintRight) - (0.025 * (3 / 4) * safeZoneH);
    private _maxY = (((linearConversion [1, (__LOCKONTIME - 0.5), _lockTime, 0.5 + 0.075*safeZoneH, (_bpos select 3), true]) + _offsetY) min __ConstraintBottom) - (0.025 * safeZoneH);

    // TRACE_3("",_boundsInput,_bpos,_lockTime);
    // TRACE_4("",_minX,_maxX,_minY,_maxY);

    __JavelinIGUITargetingGateTL ctrlSetPosition [_minX, _minY];
    __JavelinIGUITargetingGateTR ctrlSetPosition [_maxX, _minY];
    __JavelinIGUITargetingGateBL ctrlSetPosition [_minX, _maxY];
    __JavelinIGUITargetingGateBR ctrlSetPosition [_maxX, _maxY];
    {_x ctrlCommit __TRACKINTERVAL} forEach [__JavelinIGUITargetingGateTL, __JavelinIGUITargetingGateTR, __JavelinIGUITargetingGateBL, __JavelinIGUITargetingGateBR];

    __JavelinIGUITargeting ctrlShow true;
    __JavelinIGUITargetingGate ctrlShow true;
} else {
    // Not trying to lock
    __JavelinIGUITargeting ctrlShow false;
    __JavelinIGUITargetingGate ctrlShow false;
    __JavelinIGUITargetingLines ctrlShow false;
};

if (isNull _newTarget) then {
    // No target found
    _currentTarget = objNull;
    _lockStartTime = 0;
    __JavelinIGUISeek ctrlSetTextColor __ColorGray;
    _currentShooter setVariable ["ace_missileguidance_target", nil, false];

    __JavelinIGUITargetingLines ctrlShow false;

    // Disallow fire
    _fireDisabledEH = [_fireDisabledEH] call FUNC(disableFire);
} else {
    if ((!isNull _newTarget) && {_currentTarget != _newTarget}) then {
        TRACE_1("New Target, reseting locking", _newTarget);
        _lockStartTime = CBA_missionTime;
        _currentTarget = _newTarget;
    };

    if ((CBA_missionTime - _lockStartTime) > __LOCKONTIME) then { // Lock on after 3 seconds
        TRACE_2("LOCKED!", _currentTarget, _lockStartTime);
        __JavelinIGUISeek ctrlSetTextColor __ColorGreen;
        __JavelinIGUITargetingLines ctrlShow true;

        // Move target marker (the crosshair) to aimpoint on the target
        private _aimPointOnTarget = _currentTarget selectionPosition (["zamerny", "body"] select (_currentTarget isKindOf "CAManBase"));
        (worldToScreen (_currentTarget modelToWorld _aimPointOnTarget)) params [["_aposX", 0.5], ["_aposY", 0.5]];
        private _ctrlPos = ctrlPosition __JavelinIGUITargetingLineV;
        _ctrlPos set [0, _aposX + _offsetX];
        __JavelinIGUITargetingLineV ctrlSetPosition _ctrlPos;
        __JavelinIGUITargetingLineV ctrlCommit __TRACKINTERVAL;
        _ctrlPos = ctrlPosition __JavelinIGUITargetingLineH;
        _ctrlPos set [1, _aposY + _offsetY];
        __JavelinIGUITargetingLineH ctrlSetPosition _ctrlPos;
        __JavelinIGUITargetingLineH ctrlCommit __TRACKINTERVAL;

        _currentShooter setVariable ["ace_missileguidance_target", _currentTarget, false];

        // Allow fire
        _fireDisabledEH = [_fireDisabledEH] call FUNC(enableFire);

        if (diag_tickTime > _soundNextPlayTime) then {
            playSound "ACE_Javelin_Locked";
            _soundNextPlayTime = diag_tickTime + 0.25;
        };
    } else {
        // Lock in progress
        __JavelinIGUISeek ctrlSetTextColor __ColorGray;
        __JavelinIGUITargetingLines ctrlShow false;

        _currentShooter setVariable ["ace_missileguidance_target", nil, false];

        if (diag_tickTime > _soundNextPlayTime) then {
            playSound "ACE_Javelin_Locking";
            _soundNextPlayTime = diag_tickTime + 0.25;
        };
        // Disallow fire
        _fireDisabledEH = [_fireDisabledEH] call FUNC(disableFire);
    };
};

// Save arguments for next run
_this set [0, diag_frameno];
_this set [1, _currentTarget];
_this set [2, _lockStartTime];
_this set [3, _soundNextPlayTime];
_this set [4, _fireDisabledEH];
_this set [5, _nextTargetScan];