/*
	Author: IT07

	Description:
	can find a location or pos randomly on the map where there are no players

	Params:
	_this select 0: STRING - Mode to use. Options: "loc" or "pos"
	_this select 1: BOOLEAN - True if _pos needs to be a road
	_this select 2: OBJECT - Center for nearestLocations check
	_this select 3: SCALAR - Max distance in meters from center to search for _pos
	_this select 4: SCALAR - Distance in meters. Locations closer than that will be excluded
	_this select 5: SCALAR - Max prefered distance in meters from center. If not achievable, further dest will be selected
	_this select 6: SCALAR - Distance in meters to check from _cntr for players

	Returns:
	ARRAY - [name of town, town position]
*/

private ["_settings","_locPos","_loc","_locName","_ret","_continue","_settings","_blackList","_usedLocs","_checkRange","_tooCloseRange","_maxPrefered","_skipDistance","_nonPopulated","_mode","_pos","_hasPlayers","_blackPos","_checkBlackPos"];

_ret = false;
// Define settings
_settings = [["nonPopulated","noMissionPos","missionDistance"]] call VEMFr_fnc_getSetting;
_nonPopulated = _settings param [0, 1, [0]];
_blackPos = _settings param [1, [], [[]]];
_missionDistance = _settings param [2, 3000, [0]];
_checkBlackPos = false;
if (count _blackPos > 0) then
{
	_checkBlackPos = true;
};
_mode = param [0, "", [""]];
if not(_mode isEqualTo "") then
{
	_onRoad = param [1, false, [false]];
	_roadRange = 5000;
	_cntr = param [2, [], [[]]];
	if (count _cntr > 0) then
	{
		_rad = param [3, -1, [0]];
		if (_rad > -1) then
		{
			_tooCloseRange = param [4, -1, [0]];
			if (_tooCloseRange > -1) then
			{
				_maxPrefered = param [5, -1, [0]];
				if (_maxPrefered > -1) then
				{
					_skipDistance = param [6, -1, [0]];
					if (_skipDistance > -1) then
					{
						if (_mode isEqualTo "loc") then
						{
							// Get a list of locations close to _cntr (position of player)
							_locs = nearestLocations [_cntr, ["Area","BorderCrossing","CityCenter","Hill","fakeTown","Name","RockArea","Strategic","StrongpointArea","ViewPoint","NameVillage","NameCity","NameCityCapital",if(_nonPopulated isEqualTo 1)then{"nameLocal"}], _rad];
							if (count _locs > 0) then
							{
								_usedLocs = uiNamespace getVariable "VEMFrUsedLocs";
								_remLocs = [];
								_blackListMapClasses = "true" configClasses (configFile >> "CfgVemfReloaded" >> "locationBlackLists");
								_listedMaps = []; // Define
								{ // Make a list of locationBlackLists's children
									_listedMaps pushBack (configName _x);
								} forEach _blackListMapClasses;
								private ["_blackList"];
								if (worldName in _listedMaps) then { _blackList = ([["locationBlackLists", worldName],["locations"]] call VEMFr_fnc_getSetting) select 0 };
								if not(worldName in _listedMaps) then { _blackList = ([["locationBlackLists","Other"],["locations"]] call VEMFr_fnc_getSetting) select 0 };

								{ // Check _locs for invalid locations (too close, hasPlayers or inBlacklist)
									_hasPlayers = [locationPosition _x, _skipDistance] call VEMFr_fnc_checkPlayerPresence;
									if _hasPlayers then
									{
										_remLocs pushBack _x;
									};
									if not _hasPlayers then
									{
										if _checkBlackPos then
										{
											private ["_locPos","_loc"];
											_locPos = locationPosition _x;
											_loc = _x;
											{
												if (count _x isEqualTo 2) then
												{
													_pos = _x param [0, [0,0,0], [[]]];
													if not(_pos isEqualTo [0,0,0]) then
													{
														_range = _x param [1, 600, [0]];
														if ((_pos distance _locPos) < _range) then
														{
															_remLocs pushBack _loc;
														};
													};
												};
												if not(count _x isEqualTo 2) then
												{
													["fn_findPos", 0, format["found invalid entry in mission blacklist: %1", _x]] spawn VEMFr_fnc_log;
												};
											} forEach _blackPos;
										};
										if ((text _x) in _blackList) then
										{
											_remLocs pushBack _x;
										};
										if not((text _x) in _blackList) then
										{
											if (_cntr distance (locationPosition _x) < _tooCloseRange) then
											{
												_remLocs pushBack _x;
											};
											if (_cntr distance (locationPosition _x) > _tooCloseRange) then
											{
												if (([text _x, locationPosition _x]) in _usedLocs) then
												{
													_remLocs pushBack _x;
												};
											};
										};
										if (count _usedLocs > 0) then
										{
											private ["_loc"];
											_loc = _x;
											{
												if (((locationPosition _loc) distance (_x select 1)) < _missionDistance) then
												{
													_remLocs pushBack _loc;
												};
											} forEach _usedLocs;
										};
									};
								} forEach _locs;

								{ // Remove all invalid locations from _locs
									_index = _locs find _x;
									_locs deleteAt _index;
								} forEach _remLocs;

								// Check what kind of distances we have
								_far = []; // Further than _maxPrefered
								_pref = []; // Closer then _maxPrefered
								{
									_dist = _cntr distance (locationPosition _x);
									if (_dist > _maxPrefered) then
									{
										_far pushBack _x;
									};
									if (_dist < _maxPrefered) then
									{
										_pref pushBack _x;
									};
								} forEach _locs;

								// Check if there are any prefered locations. If yes, randomly select one
								if (count _pref > 0) then
								{
									_loc = selectRandom _pref;
								};

								// Check if _far has any locations and if _pref is empty
								if (count _far > 0) then
								{
									if (count _pref isEqualTo 0) then
									{
										_loc = selectRandom _far;
									};
								};

								// Validate _locs just to prevent the .RPT from getting spammed
								if (count _locs > 0) then
								{
									// Return Name and POS
									_ret = [text _loc, locationPosition _loc];
									(uiNamespace getVariable "VEMFrUsedLocs") pushBack _ret;
								};
							};
						};
						if (_mode isEqualTo "pos") then
						{
							_valid = false;
							for "_p" from 1 to 10 do
							{
								if (_ret isEqualType true) then
								{
									if not _ret then
									{
										_pos = [_cntr, _tooCloseRange, _rad, 2, 0, 500, 0] call BIS_fnc_findSafePos;
										if _onRoad then
										{
											_roads = _pos nearRoads _roadRange;
											if (count _roads > 0) then
											{
												private ["_closest","_dist"];
												_closest = ["", _roadRange];
												{ // Find the closest road
													_dist = _x distance _pos;
													if (_dist < (_closest select 1)) then
													{
														_closest = [_x, _dist];
													};
												} forEach _roads;
												_pos = position (_closest select 0);
											};
										};
										_hasPlayers = [_pos, _skipDistance] call VEMFr_fnc_checkPlayerPresence;
										if not(_hasPlayers) then
										{
											_ret = _pos;
										};
									};
								};
							};
						};
					};
				};
			};
		};
	};
};

_ret
