/*
██╗░░░██╗████████╗██╗██╗░░░░░░██████╗
██║░░░██║╚══██╔══╝██║██║░░░░░██╔════╝
██║░░░██║░░░██║░░░██║██║░░░░░╚█████╗░
██║░░░██║░░░██║░░░██║██║░░░░░░╚═══██╗
╚██████╔╝░░░██║░░░██║███████╗██████╔╝
░╚═════╝░░░░╚═╝░░░╚═╝╚══════╝╚═════╝░
*/
const resName = GetParentResourceName();
const allJobsStatisticsDiv = document.getElementById('all-jobs-statistics').getContext('2d');
const jobStatisticsDiv = document.getElementById('job-statistics-chart').getContext('2d');
let TRANSLATIONS = {};
let ENGLISH_TRANSLATIONS = {};
let MARKERS_INFOS = {};
let ACTIONS_LABELS = {};
function translateEverything() {
	$("body").find("[data-translation-id], [data-bs-toggle='tooltip']").each(function() {
		let translationId = $(this).data("translationId")
		if( $(this).data("bsToggle") == "tooltip" ) {
			if ($(this).tooltip) {
				$(this).tooltip('dispose');
			}
	
			$(this).attr("data-bs-title", getLocalizedText(translationId));
			$(this).tooltip();
		} else if( $(this).hasClass("form-control") ) {
			$(this).attr("placeholder", getLocalizedText(translationId));
		} else {
			$(this).prop("innerHTML", getLocalizedText(translationId));
		}
	})
	MARKERS_INFOS = {
		["stash"]: { 
			label: getLocalizedText("menu:dynamic:marker_info:stash"),
			settingsName: getLocalizedText("menu:dynamic:marker_info:stash_settings"),
			isJobMarker: true,
			isPublicMarker: true,
			requiresDataUpdate: false
		},
		["armory"]: { 
			label: getLocalizedText("menu:dynamic:marker_info:armory"),
			settingsName: getLocalizedText("menu:dynamic:marker_info:armory_settings"),
			isJobMarker: true,
			isPublicMarker: true,
			requiresDataUpdate: true,
			framework: "ESX"
		},
		["safe"]: { 
			label: getLocalizedText("menu:dynamic:marker_info:safe"),
			settingsName: null,
			isJobMarker: true,
			isPublicMarker: true,
			requiresDataUpdate: false,
			framework: "ESX"
		},
		["garage"]: { 
			label: getLocalizedText("menu:dynamic:marker_info:temporary_garage"),
			settingsName: getLocalizedText("menu:dynamic:marker_info:temporary_garage_settings"),
			isJobMarker: true,
			isPublicMarker: true,
			requiresDataUpdate: true
		},
		["garage_buyable"]: { 
			label: getLocalizedText("menu:dynamic:marker_info:garage_buyable"),
			settingsName: getLocalizedText("menu:dynamic:marker_info:garage_buyable_settings"),
			isJobMarker: true,
			isPublicMarker: true,
			requiresDataUpdate: true
		},
		["garage_owned"]: { 
			label: getLocalizedText("menu:dynamic:marker_info:garage_owned"),
			settingsName: getLocalizedText("menu:dynamic:marker_info:garage_owned_settings"),
			isJobMarker: true,
			isPublicMarker: true,
			requiresDataUpdate: true
		},
		["boss"]: { 
			label: getLocalizedText("menu:dynamic:marker_info:boss"),
			settingsName: getLocalizedText("menu:dynamic:marker_info:boss_settings"),
			isJobMarker: true,
			isPublicMarker: false,
			requiresDataUpdate: true
		},
		["wardrobe"]: { 
			label: getLocalizedText("menu:dynamic:marker_info:wardrobe"),
			settingsName: null,
			isJobMarker: true,
			isPublicMarker: true,
			requiresDataUpdate: true
		},
		["job_outfit"]: { 
			label: getLocalizedText("menu:dynamic:marker_info:job_outfit"),
			settingsName: getLocalizedText("menu:dynamic:marker_info:job_outfit_settings"),
			isJobMarker: true,
			isPublicMarker: true,
			requiresDataUpdate: true
		},
		["shop"]: { 
			label: getLocalizedText("menu:dynamic:marker_info:shop"),
			settingsName: getLocalizedText("menu:dynamic:marker_info:shop_settings"),
			isJobMarker: true,
			isPublicMarker: true,
			requiresDataUpdate: true
		},
		["market"]: { 
			label: getLocalizedText("menu:dynamic:marker_info:market"),
			settingsName: getLocalizedText("menu:dynamic:marker_info:market_settings"),
			isJobMarker: true,
			isPublicMarker: true,
			requiresDataUpdate: true
		},
		["harvest"]: { 
			label: getLocalizedText("menu:dynamic:marker_info:harvest"),
			settingsName: getLocalizedText("menu:dynamic:marker_info:harvest_settings"),
			isJobMarker: true,
			isPublicMarker: true,
			requiresDataUpdate: true
		},
		["process"]: { 
			label: getLocalizedText("menu:dynamic:marker_info:process"),
			settingsName: getLocalizedText("menu:dynamic:marker_info:process_settings"),
			isJobMarker: true,
			isPublicMarker: true,
			requiresDataUpdate: true
		},
		["crafting_table"]: { 
			label: getLocalizedText("menu:dynamic:marker_info:crafting_table"),
			settingsName: getLocalizedText("menu:dynamic:marker_info:crafting_table_settings"),
			isJobMarker: true,
			isPublicMarker: true,
			requiresDataUpdate: true
		},
		["teleport"]: { 
			label: getLocalizedText("menu:dynamic:marker_info:teleport"),
			settingsName: getLocalizedText("menu:dynamic:marker_info:teleport_settings"),
			isJobMarker: true,
			isPublicMarker: true,
			requiresDataUpdate: true
		},
		["weapon_upgrader"]: { 
			label: getLocalizedText("menu:dynamic:marker_info:weapon_upgrader"),
			settingsName: getLocalizedText("menu:dynamic:marker_info:weapon_upgrader_settings"),
			isJobMarker: true,
			isPublicMarker: true,
			requiresDataUpdate: true
		},
		["duty"]: { 
			label: getLocalizedText("menu:dynamic:marker_info:duty"),
			settingsName: null,
			isJobMarker: true,
			isPublicMarker: false,
			requiresDataUpdate: true
		},
		["job_shop"]: { 
			label: getLocalizedText("menu:dynamic:marker_info:job_shop"),
			settingsName: getLocalizedText("menu:dynamic:marker_info:job_shop_settings"),
			isJobMarker: false,
			isPublicMarker: true,
			requiresDataUpdate: true
		},
	}
	ACTIONS_LABELS = [
		{action: "actionsMenuEnabled", label: getLocalizedText("menu:job_settings:can_open_actions_menu")},
		{action: "canRepairVehicles", label: getLocalizedText("menu:job_settings:enable_repair_vehicles")},
		{action: "canCheckDrivingLicense", label: getLocalizedText("menu:job_settings:enable_check_driving_license")},
		{action: "canCheckWeaponLicense", label: getLocalizedText("menu:job_settings:enable_check_weapon_license")},
		{action: "enableBilling", label: getLocalizedText("menu:job_settings:enable_billing")},
		{action: "canHandcuff", label: getLocalizedText("menu:job_settings:enable_handcuff_players")},
		{action: "placeableObjects", label: getLocalizedText("menu:job_settings:placeable_objects")},
		{action: "canLockpickCars", label: getLocalizedText("menu:job_settings:enable_lockpick_players")},
		{action: "whitelisted", label: getLocalizedText("menu:job_settings:whitelisted")},
		{action: "canRevive", label: getLocalizedText("menu:job_settings:enable_revive")},
		{action: "canWashVehicles", label: getLocalizedText("menu:job_settings:enable_wash_vehicles")},
		{action: "canRob", label: getLocalizedText("menu:job_settings:enable_search_players")},
		{action: "canCheckIdentity", label: getLocalizedText("menu:job_settings:enable_check_identities")},
		{action: "canImpoundVehicles", label: getLocalizedText("menu:job_settings:enable_impound_vehicles")},
		{action: "canCheckVehicleOwner", label: getLocalizedText("menu:job_settings:enable_check_vehicle_owner")},
		{action: "canHeal", label: getLocalizedText("menu:job_settings:enable_heal")},
	]
} 
async function refreshTranslations(locale) {
	let rawEnglishTranslations = await $.get("menu_translations/en.json");
	ENGLISH_TRANSLATIONS = typeof rawEnglishTranslations == "object" ? rawEnglishTranslations : JSON.parse(rawEnglishTranslations);
	let rawTranslations = await $.get(`menu_translations/${locale}.json`);
	TRANSLATIONS = typeof rawTranslations == "object" ? rawTranslations : JSON.parse(rawTranslations);
	translateEverything();
}
async function loadTranslations() {
	const locale = await $.post(`https://${resName}/getLocale`);
	refreshTranslations(locale);
} loadTranslations();
function getLocalizedText(text) {
	return TRANSLATIONS[text] || ENGLISH_TRANSLATIONS[text] || text;
}
async function getFramework() {
	const framework = await $.post(`https://${resName}/getFramework`);
	return framework;
}
const allJobsStatisticsChart = new Chart(allJobsStatisticsDiv, {
	type: 'bar',
	data: {
		labels: "Jobs",
		datasets: []
	},
	options: {
		scales: {
			y: {
				beginAtZero: true
			}
		},
	}
});
const jobStatisticsChart = new Chart(jobStatisticsDiv, {
	type: 'bar',
	data: {
		labels: "Ranks",
		datasets: []
	},
	options: {
		scales: {
			y: {
				beginAtZero: true
			}
		},
	}
});
// Fetch all the forms we want to apply custom Bootstrap validation styles to
var forms = document.querySelectorAll('.needs-validation')
// Loop over them and prevent submission
Array.prototype.slice.call(forms)
.forEach(function (form) {
	form.addEventListener('submit', function (event) {
	event.preventDefault();
	form.classList.add('was-validated')
	}, false)
})
$(".max-two-decimals").change(function() {
	if(isNaN(this.value)) {
		return
	}
	let number = parseFloat(this.value);
	if(number) {
		this.value = number.toFixed(2);
	}
})
function getValidId(text) {
	text = text.toLowerCase();
	text = text.replace(/[^a-zA-Z0-9]/g,'_');
	return text
}
$(".id").on("input", function() {
	let text = $(this).val();
	
	$(this).val( getValidId(text) );
})
function componentToHex(c) {
	var hex = c.toString(16);
	return hex.length == 1 ? "0" + hex : hex;
  }
  
function rgbToHex(r, g, b) {
	return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
}  
function hexToRgb(hex) {
	var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
	return result ? {
	  r: parseInt(result[1], 16),
	  g: parseInt(result[2], 16),
	  b: parseInt(result[3], 16)
	} : null;
}
function getVehicleLabel(vehicleModel, cb) {
	$.post(`https://${resName}/get-vehicle-label`, JSON.stringify({vehicleModel: vehicleModel}), cb)
}
// Disables enter
$(document).on("keypress", 'form', function (e) {
    var code = e.keyCode || e.which;
    if (code == 13) {
        e.preventDefault();
        return false;
    }
});
/* Dialogs */
function inputDialog(title, data, yesCallback) {
	$("#input-text-dialog-title").text(title);
	var inputModal = $("#input-text-dialog-modal");
	// Removes old data
	inputModal.find(".modal-body form").empty();
	data.forEach(currentData => {
		var id = currentData.id;
		var label = currentData.label;
		var defaultValue = currentData.default !== undefined ? currentData.default : "";
		var type = currentData.type || "text";
		if (type === "button") {
			var button = $(``);
			button.click(function () {
				currentData.buttonCallback(inputModal);
			});
			inputModal.find(".modal-body form").append(button);
		} else if (type === "select") {
			var select = $(``)
			var options = currentData.options
			options.forEach(option => {
				var optionElement = $(``)
				select.append(optionElement);
			})
			inputModal.find(".modal-body form").append(select);
		} else if (type === "switch") {
			var switchInput = $(`
			
				
				
			
`);
			inputModal.find(".modal-body form").append(switchInput);
			$(`#modal-${id}`).prop("checked", defaultValue)
		} else {
			let isAnId = currentData.isId || false
			var formGroup = $(
				``
			)
			inputModal.find(".modal-body form").append(formGroup)
			let inputDiv = $(`#modal-${id}`);
			inputDiv.unbind('input');
			if(isAnId) {
				inputDiv.on('input', function() {
					let text = inputDiv.val();
					text = text.toLowerCase();
					text = text.replace(/[^a-zA-Z0-9]/g,'_');
					inputDiv.val(text);
				});
			}
		}
	})
	inputModal.modal("show");
	$("#input-text-dialog-confirm").off('click');
	$("#input-text-dialog-confirm").click(function () {
		var areInputsValid = true;
		var inputs = inputModal.find(".form-control, .form-select, :checkbox");
		var length = inputs.length;
		var data = {};
		inputs.each(function (index, element) {
			var text = $(element).val();
			if (text || $(element).is(":checkbox")) {
				$(element).removeClass("is-invalid");
				var id = $(element).data("id");
				if ($(element).is(":checkbox")) {
					data[id] = $(element).is(':checked');
				} else {
					data[id] = text;
				}
			} else {
				$(element).addClass("is-invalid");
				areInputsValid = false;
			}
		});
		inputModal.modal("hide");
		yesCallback(data);
	})
}
function showError(msg){
	$("#notification-message").text(msg);
	$("#notification-modal").modal("show");
}
function accountsDialog(cb) {
	let accountsModal = $("#input-accounts-dialog-modal");
	let accountsList = $("#accounts-list");
	$.post(`https://${resName}/getAllAccounts`, {}, function (accounts) {
		accountsList.empty();
		for(const[accountName, accountLabel] of Object.entries(accounts)) {
			let accountDiv = $(`
				${accountLabel}
			`);
			accountDiv.click(function() {
				accountsModal.modal("hide");
				cb(accountName);
			});
			accountsList.append(accountDiv);
		}
		accountsModal.modal("show");
	})
}
async function getCurrentCoordsAndHeading() {
	return new Promise((resolve, reject) => {
		$.post(`https://${resName}/get-current-coords`, {}, function (coords) {
			resolve(coords);
		});
	});
}
/*
██████╗░░█████╗░███╗░░██╗██╗░░██╗░██████╗
██╔══██╗██╔══██╗████╗░██║██║░██╔╝██╔════╝
██████╔╝███████║██╔██╗██║█████═╝░╚█████╗░
██╔══██╗██╔══██║██║╚████║██╔═██╗░░╚═══██╗
██║░░██║██║░░██║██║░╚███║██║░╚██╗██████╔╝
╚═╝░░╚═╝╚═╝░░╚═╝╚═╝░░╚══╝╚═╝░░╚═╝╚═════╝░
*/
let ranksDataTable = $("#ranks-container").DataTable( {
	"lengthMenu": [5, 10, 15, 20],
	"pageLength": 10,
	"createdRow": function ( row, data, index ) {
		$(row).addClass("clickable");
		$(row).click(function() {
			let editRankModal = $("#edit-rank");
			let rankId = data[0];
			let rankLabel = data[1];
			let rankName = data[2];
			let rankGrade = data[3];
			let rankSalary = data[4];
			$("#edit-rank-label").val(rankLabel);
			$("#edit-rank-name").val(rankName);
			$("#edit-rank-grade").val(rankGrade);
			$("#edit-rank-salary").val(rankSalary);
			editRankModal.data("rankId", rankId);
			editRankModal.modal("show");
		})
	},
	"columnDefs": [{"defaultContent": "???", "targets": "_all"}]
} );
async function deleteRank(jobName, rankId) {
	if(! await confirmDeletion(getLocalizedText("menu:do_you_want_to_delete_the_rank"))) return;
	const data = await $.post(`https://${resName}/delete-rank`, JSON.stringify({ rankId: rankId }));
	// Removes deleted row
	if (data.isSuccessful) {
		refreshJobRanks(jobName)
	} else {
		showError(data.message)
	}
}
function fillJobRanks(ranks) {
	ranksDataTable.clear();
	for(const[_, gradeData] of Object.entries(ranks)) {
		ranksDataTable.row.add( [gradeData.id, gradeData.label, gradeData.name, gradeData.grade, gradeData.salary] );
	}
	ranksDataTable.draw();
}
$("#edit-rank-form").submit(function(event) {
	if (!this.checkValidity()) {
		event.preventDefault();
		event.stopPropagation();
		return;
	} else {
		$(this).removeClass("was-validated");
		$("#create-rank").modal("hide");
	}
	
	let data = {
		rankLabel: $("#edit-rank-label").val(),
		rankName: $("#edit-rank-name").val(),
		rankGrade: parseInt( $("#edit-rank-grade").val() ),
		rankSalary: parseInt( $("#edit-rank-salary").val() ),
		rankId: $("#edit-rank").data("rankId")
	}
	$.post(`https://${resName}/updateRank`, JSON.stringify(data), function (resultData) {
		// Updates old row field with new values
		if (resultData.isSuccessful) {
			refreshJobRanks( $("#edit-job").data("jobName") );
		} else {
			showError(resultData.message)
		}
	});
	$("#edit-rank").modal("hide");
})
$("#edit-rank-delete-btn").click(function() {
	let jobName = $("#edit-job").data("jobName");
	let rankId = $("#edit-rank").data("rankId");
	deleteRank(jobName, rankId);
})
$("#create-rank-btn").click(function() {
	// Reset previous inputs
	$("#create-rank-label").val("");
	$("#create-rank-name").val("");
	$("#create-rank-grade").val("");
	$("#create-rank-salary").val("");
	$("#create-rank").modal("show");
});
// Automatically fills the id from the label
$("#create-rank-label").on("input", function(){
	let label = $(this).val();
	let id = getValidId(label);
	$("#create-rank-name").val(id);
})
// Automatically fills the id from the label
$("#edit-rank-label").on("input", function(){
	let label = $(this).val();
	let id = getValidId(label);
	$("#edit-rank-name").val(id);
})
$("#create-rank-form").submit(function(event) {
	if(isThereAnyErrorInForm(event)) return;
	let jobName = $("#edit-job").data("jobName");
	let data = {
		rankLabel: $("#create-rank-label").val(),
		rankName: $("#create-rank-name").val(),
		rankGrade: parseInt( $("#create-rank-grade").val() ),
		rankSalary: parseInt( $("#create-rank-salary").val() ),
		jobName: jobName
	}
	$.post(`https://${resName}/create-new-rank`, JSON.stringify(data), function (data) {
		if (data.isSuccessful) {
			refreshJobRanks(jobName)
		} else {
			showError(data.message)
		}
	});
	$("#create-rank").modal("hide");
})
function refreshJobRanks(jobName) {
	$.post(`https://${resName}/retrieveJobRanks`, JSON.stringify({ jobName: jobName }), function (ranks) {
		if (ranks) {
			fillJobRanks(ranks)
		}
	});
}
/*
░░░░░██╗░█████╗░██████╗░░██████╗
░░░░░██║██╔══██╗██╔══██╗██╔════╝
░░░░░██║██║░░██║██████╦╝╚█████╗░
██╗░░██║██║░░██║██╔══██╗░╚═══██╗
╚█████╔╝╚█████╔╝██████╦╝██████╔╝
░╚════╝░░╚════╝░╚═════╝░╚═════╝░
*/
var allJobs = {};
async function refresh() {
	fillPublicMarkers();
	const jobs = await $.post(`https://${resName}/getJobsData`, {});
	allJobs = jobs;
		
	fillJobs(jobs);
}
$("#create-job-btn").click(function () {
	inputDialog(getLocalizedText("menu:create_new_job"), [
		{ id: "jobLabel", label: getLocalizedText("menu:dynamic:new_job_label") },
		{ id: "jobName", label: getLocalizedText("menu:dynamic:new_job_name"), isId: true },
	], function (data) {
		$.post(`https://${resName}/create-new-job`, JSON.stringify({ jobLabel: data.jobLabel, jobName: data.jobName }), function (data) {
			if (data.isSuccessful) {
				refresh()
			} else {
				showError(data.message)
			}
		});
	});
})
function exitFromEditJob(){
	// Resets current active tab (ranks is the default one)
	$("#edit-job").find(".nav-link, .tab-pane").each(function() {
		if($(this).data("isDefault") == "1") {
			$(this).addClass(["active", "show"])
		} else {
			$(this).removeClass(["active", "show"])
		}
	})
	refresh();
	$("#edit-job").hide();
	$("#job-creator").show();
}
async function deleteJob(jobName) {
	if(! await confirmDeletion(getLocalizedText("menu:dynamic:delete_job_confirm"))) return;
	
	const data = await $.post(`https://${resName}/delete-job`, JSON.stringify({ jobName: jobName }));
	data.isSuccessful ? exitFromEditJob() : showError(data.message);
}
$("#delete-job-btn").click(function() {
	let jobName = $("#edit-job").data("jobName");
	deleteJob(jobName);
})
$("#edit-job-label").on("input", function(){
	let label = $(this).val();
	let id = getValidId(label);
	$("#edit-job-name").val(id);
})
function editJob(jobData) {
	let editJobDiv = $("#edit-job");
	editJobDiv.data("jobName", jobData.name);
	// Chart with ranks 
	loadRanksDistrubutions();
	// Job settings
	$("#edit-job-label").val(jobData.label);
	$("#edit-job-name").val(jobData.name);
	// Fills actions in settings
	if(jobData.actions) {
		for(const[actionName, isEnabled] of Object.entries(jobData.actions)) {
			$("#job-settings-actions").find(`[data-action-name=${actionName}]`).prop("checked", isEnabled)
		}
	}
	// Fill placeable objects
	$("#job-placeable-objects-list").empty();
	$("#job-placeable-objects-no-objects-text").show(); // It will be hidden if there are objects
	for(const [model, objectData] of Object.entries(jobData.actions?.placeableObjects || {})) {
		addPlaceableObject(model, objectData.label, objectData.limit);
	}
	$("#edit-job-text").text(jobData.label);
	fillJobRanks(jobData.ranks);
	fillJobMarkers();
	$("#job-creator").hide();
	editJobDiv.show();
	jobTour();
}
$("#edit-job-close-btn").click(exitFromEditJob);
function addPlaceableObject(model, label, limit) {
	const div = $(`
		
	`);
	div.find(".delete-object-btn").click(function() {
		div.remove();
		if($("#job-placeable-objects-list").children().length == 0) {
			$("#job-placeable-objects-no-objects-text").show();
		}
	});
	div.find(".object-model").val(model || "");
	div.find(".object-label").val(label || "");
	div.find(".object-limit").val(limit || 1);
	$("#job-placeable-objects-no-objects-text").hide();
	$("#job-placeable-objects-list").append(div);
}
$("#job-placeable-objects-add-btn").click(function() {
	addPlaceableObject();
});
$("#job-settings").submit(function(event) {
	if (!this.checkValidity()) {
		event.stopPropagation();
		event.preventDefault();
		return;
	} else {
		$(this).removeClass("was-validated");
	}
	let actions = {};
	$("#job-settings-actions").find(".job-action").each(function() {
		let actionName = $(this).data("actionName");
		actions[actionName] = $(this).prop("checked");
	})
	let placeableObjects = {};
	
	$("#job-placeable-objects-list").find(".placeable-object").each(function() {
		let model = $(this).find(".object-model").val();
		placeableObjects[model] = {
			label: $(this).find(".object-label").val(),
			limit: parseInt( $(this).find(".object-limit").val() )
		}
	});
	actions["placeableObjects"] = placeableObjects;
	let oldJobName = $("#edit-job").data("jobName");
	let jobName = $("#edit-job-name").val();
	let jobLabel = $("#edit-job-label").val();
	let data = {
		oldJobName,
		jobName,
		jobLabel,
		actions
	}
	$.post(`https://${resName}/update-job`, JSON.stringify(data), function (resultData) {
		// Updates old job with new values
		if (resultData.isSuccessful) {
			exitFromEditJob();
		} else {
			showError(resultData.message)
		}
	});
})
let jobsDataTable = $("#jobs-container").DataTable( {
	"lengthMenu": [5, 10, 15, 20],
	"pageLength": 10,
	"createdRow": function ( row, data, index ) {
		$(row).addClass("clickable");
		$(row).click(function() {
			let jobName = data[1];
			editJob(allJobs[jobName])
		})
	},
	"columnDefs": [{"defaultContent": "???", "targets": "_all"}]
} );
function fillJobs(jobs) {
	jobsDataTable.clear();
	for (const [_, job] of Object.entries(jobs)) {
		jobsDataTable.row.add( [job.label, job.name, Object.entries(job.ranks).length] );
	}
	jobsDataTable.draw();
}
/*
███╗░░░███╗░█████╗░██████╗░██╗░░██╗███████╗██████╗░░██████╗
████╗░████║██╔══██╗██╔══██╗██║░██╔╝██╔════╝██╔══██╗██╔════╝
██╔████╔██║███████║██████╔╝█████═╝░█████╗░░██████╔╝╚█████╗░
██║╚██╔╝██║██╔══██║██╔══██╗██╔═██╗░██╔══╝░░██╔══██╗░╚═══██╗
██║░╚═╝░██║██║░░██║██║░░██║██║░╚██╗███████╗██║░░██║██████╔╝
╚═╝░░░░░╚═╝╚═╝░░╚═╝╚═╝░░╚═╝╚═╝░░╚═╝╚══════╝╚═╝░░╚═╝╚═════╝░
*/
let allMarkers = {};
let jobMarkersDataTable = $("#job-markers-container").DataTable( {
	"lengthMenu": [5, 10, 15, 20],
	"pageLength": 10,
	"createdRow": function ( row, data, index ) {
		$(row).addClass("clickable");
		$(row).click(function() {
			let markerId = data[0];
			editMarker(markerId);
		})
	},
	"columnDefs": [{"defaultContent": "???", "targets": "_all"}]
} );
let publicMarkersDataTable = $("#public-markers-container").DataTable( {
	"lengthMenu": [5, 10, 15, 20],
	"pageLength": 10,
	"createdRow": function ( row, data, index ) {
		$(row).addClass("clickable");
		$(row).click(function() {
			let markerId = data[0];
			editMarker(markerId);
		})
	},
	"columnDefs": [{"defaultContent": "???", "targets": "_all"}]
} );
function fillJobMarkers(markerToEdit) {
	let jobName = $("#edit-job").data("jobName");
	$.post(`https://${resName}/retrieveJobMarkers`, JSON.stringify({ jobName: jobName }), function (markers) {
		allMarkers = {};
		// Manually insert each marker to avoid wrong conversion between lua table first index (1) and javascript object first index (0)
		for(const[k, markerData] of Object.entries(markers)) {
			allMarkers[markerData.id] = markerData;
		}
		jobMarkersDataTable.clear();
		for(const[_, markerData] of Object.entries(markers)) {
			let typeLabel = MARKERS_INFOS[markerData.type]?.label;
			
			jobMarkersDataTable.row.add( [markerData.id || "Unknown", markerData.label || "No name", typeLabel, markerData.coords.x, markerData.coords.y, markerData.coords.z] );
		}
	
		jobMarkersDataTable.draw();
		if(markerToEdit) {
			editMarker(markerToEdit);
		}
	})
}
function fillPublicMarkers(markerToEdit) {
	$.post(`https://${resName}/retrieveJobMarkers`, JSON.stringify({ jobName: "public_marker" }), function (markers) {
		allMarkers = {};
		// Manually insert each marker to avoid wrong conversion between lua table first index (1) and javascript object first index (0)
		for(const[k, markerData] of Object.entries(markers)) {
			allMarkers[markerData.id] = markerData;
		}
		
		publicMarkersDataTable.clear();
		for(const[_, markerData] of Object.entries(markers)) {
			let typeLabel = MARKERS_INFOS[markerData.type]?.label;
			
			publicMarkersDataTable.row.add( [markerData.id, markerData.label || "No name", typeLabel, markerData.coords.x, markerData.coords.y, markerData.coords.z] );
		}
	
		publicMarkersDataTable.draw();
		if(markerToEdit) {
			editMarker(markerToEdit);
		}
	})
}
function getOffDutyName(name) {
    return "off_" + name;
}
function getOnDutyName(name) {
    return name.replace("off_", "");
}
function isOffDutyName(name) {
    return name.includes("off_");
}
async function createJobMarker(jobName) {
	let allowedMarkers = [];
	for(const[markerType, markerInfo] of Object.entries(MARKERS_INFOS)) {
		if(markerInfo.framework != undefined && markerInfo.framework != await getFramework()) continue;
		if(!markerInfo.isJobMarker) continue;
		allowedMarkers.push({
			value: markerType,
			label: markerInfo.label
		})
	}
	inputDialog(getLocalizedText("menu:dynamic:job_markers:create_marker"), [
		{ id: "markerType", label: "Marker Type:", type: "select", options: allowedMarkers },
		{ id: "label", label: getLocalizedText("menu:dynamic:job_markers:label"), type: "text", default: getLocalizedText("menu:dynamic:default") },
		{ id: "markerCoordsX", label: getLocalizedText("menu:dynamic:job_markers:coord_x"), type: "number" },
		{ id: "markerCoordsY", label: getLocalizedText("menu:dynamic:job_markers:coord_y"), type: "number" },
		{ id: "markerCoordsZ", label: getLocalizedText("menu:dynamic:job_markers:coord_z"), type: "number" },
		{
			id: "currentCoordsBtn", label: getLocalizedText("menu:dynamic:job_markers:current_coords"), type: "button", buttonType: "btn-success",
			buttonCallback: async function (modal) {
				const coords = await placeEntity();
				if(!coords) return;
				modal.find("#modal-markerCoordsX").val(coords.x)
				modal.find("#modal-markerCoordsY").val(coords.y)
				modal.find("#modal-markerCoordsZ").val(coords.z)
			}
		},
		{ id: "markerMinGrade", label: getLocalizedText("menu:dynamic:job_markers:min_grade"), type: "number", default: 0 },
	], async function (data) {
		data.jobName = jobName
		const resultData = await $.post(`https://${resName}/create-marker`, JSON.stringify(data));
		if (resultData.isSuccessful) {
			fillJobMarkers(resultData.markerId);
			if(!isOffDutyName(jobName) && await getFramework() == "ESX" && data.markerType == "duty") {
				const duplicateForOffDuty = await swal({
					title: getLocalizedText("menu:note"),
					text: getLocalizedText("menu:do_you_want_to_create_it_also_for_off_duty_job"),
					icon: "info",
					buttons: true,
					dangerMode: false,
				});
				if(!duplicateForOffDuty) return;
				data.jobName = getOffDutyName(jobName);
				const resultData = await $.post(`https://${resName}/create-marker`, JSON.stringify(data));
				if (resultData.isSuccessful) {
					fillJobMarkers(resultData.markerId);
				} else {
					showError(resultData.message)
				}
			}
		} else {
			showError(resultData.message)
		}
	})
}
$("#create-job-marker-btn").click(function() {
	let jobName = $("#edit-job").data("jobName");
	createJobMarker(jobName);
})
async function createPublicMarker() {
	let allowedMarkers = [];
	for(const[markerType, markerInfo] of Object.entries(MARKERS_INFOS)) {
		if(markerInfo.framework == undefined || markerInfo.framework == await getFramework()) {
			if(markerInfo.isPublicMarker) {
				allowedMarkers.push({
					value: markerType,
					label: markerInfo.label
				})
			}
		}
	}
	inputDialog(getLocalizedText("menu:dynamic:public_markers:create_public_marker"), [
		{ id: "markerType", label: "Marker Type:", type: "select", options: allowedMarkers },
		{ id: "label", label: getLocalizedText("menu:dynamic:public_markers:label"), type: "text", default: getLocalizedText("menu:dynamic:default") },
		{ id: "markerCoordsX", label: getLocalizedText("menu:dynamic:public_markers:coord_x"), type: "number" },
		{ id: "markerCoordsY", label: getLocalizedText("menu:dynamic:public_markers:coord_y"), type: "number" },
		{ id: "markerCoordsZ", label: getLocalizedText("menu:dynamic:public_markers:coord_z"), type: "number" },
		{
			id: "currentCoordsBtn", label: getLocalizedText("menu:dynamic:public_markers:current_coords"), type: "button", buttonType: "btn-success",
			buttonCallback: async function (modal) {
				const coords = await placeEntity();
				if(!coords) return;
				modal.find("#modal-markerCoordsX").val(coords.x)
				modal.find("#modal-markerCoordsY").val(coords.y)
				modal.find("#modal-markerCoordsZ").val(coords.z)
			}
		},
	], function (data) {
		$.post(`https://${resName}/create-public-marker`, JSON.stringify(data), function (data) {
			if (data.isSuccessful) {
				fillPublicMarkers(data.markerId);
			} else {
				showError(data.message)
			}
		});
	})
}
$("#create-public-marker-btn").click(createPublicMarker);
function hideAllMarkerSettings() {
	$("#edit-marker-form").find(".edit-marker-settings").each(function() {
		$(this).find(".form-control").each(function(index, element) {
			if($(element).prop("required")) {
				$(element).prop("required", false);
				$(element).data("isActuallyRequired", true);
			}
		});
		$(this).hide();
	})
}
function showMarkerSettings(markerType) {
	hideAllMarkerSettings();
	$("#edit-marker-form").find(`.edit-marker-settings`).each(function() {
		if( $(this).data("markerType") != markerType ) return;
		$(this).find(".form-control").each(function(index, element) {
			if( $(element).data("isActuallyRequired") ) {
				$(element).prop("required", true);
			}
		});
		$(this).show();
		return;
	})
}
function editMarker(markerId) {
	$("#edit-marker-form").removeClass("was-validated");
	let markerData = allMarkers[markerId];
	if(!markerData) {
		console.log("Couldn't find marker " + markerId);
		
		console.log(`Existing markers for job '${ $("#edit-job").data("jobName") }': `)
		for(const[key, value] of Object.entries(allMarkers)) {
			console.log(`	Marker ID '${key}'`);
		}
		
		return
	}
	let isMarkerPublic = markerData.jobName == "public_marker";
	
	$("#edit-marker-form").data("isPublic", isMarkerPublic);
	$("#edit-marker-label").val(markerData.label);
	$("#edit-marker-type").val(markerData.markerType);
	changeMarkerGradeType(markerData.gradesType);
	if(markerData.gradesType === "specificGrades") {
		setSpecificGrades(markerData.specificGrades);
	} else if(markerData.gradesType === "minimumGrade") {
		$("#edit-marker-min-grade").val(markerData.minGrade);
	}
	$("#edit-marker-scale-x").val(markerData.scale.x);
	$("#edit-marker-scale-y").val(markerData.scale.y);
	$("#edit-marker-scale-z").val(markerData.scale.z);
	
	$("#edit-marker-coord-x").val(markerData.coords.x);
	$("#edit-marker-coord-y").val(markerData.coords.y);
	$("#edit-marker-coord-z").val(markerData.coords.z);
	
	$("#edit-marker-color").val(rgbToHex(markerData.color.r, markerData.color.g, markerData.color.b));
	$("#edit-marker-alpha").val(markerData.color.alpha);
	
	// Map blip
	$("#edit-marker-sprite-id").val(markerData.blip?.spriteId);
	$("#edit-marker-blip-color").val(markerData.blip?.color);
	$("#edit-marker-blip-scale").val(markerData.blip?.scale);
	toggleBlipInputs(markerData.blip?.spriteId ? true : false);
	// NPC
	$("#edit-marker-npc-model").val(markerData.ped?.model);
	$("#edit-marker-npc-heading").val(markerData.ped?.heading);
	toggleNpcInputs(markerData.ped?.model ? true : false);
	
	// Object
	$("#edit-marker-object-model").val(markerData.object?.model);
	$("#edit-marker-object-heading").val(markerData.object?.heading);
	toggleObjectInputs(markerData.object?.model ? true : false);
	// Minimum grade / specific grade inputs
	$("#edit-marker-min-grade").prop("disabled", isMarkerPublic);
	$("input[name=markerGradeType]").prop("disabled", isMarkerPublic);
	$("#edit-marker-min-grade").val(markerData.minGrade || 0);
	let settingsLabel = MARKERS_INFOS[markerData.type].settingsName;
	if(settingsLabel) {
		$("#specific-marker-settings").show();
		$("#specific-marker-settings-label").text(settingsLabel);
		
		showMarkerSettings(markerData.type);
	} else {
		$("#specific-marker-settings").hide();
		hideAllMarkerSettings();
	}
	setCurrentMarkerData(markerData.type, markerData.data);
	let editMarkerModal = $("#edit-marker-dialog-modal");
	editMarkerModal.modal("show");
	editMarkerModal.data("markerId", markerId);
}
function changeMarkerGradeType(type) {
	$(`input[type=radio][name="markerGradeType"][value="${type}"]`).prop("checked", true);
	switch(type) {
		case "minimumGrade": {
			$("#edit-marker-min-grade").prop("required", true);
			$("#edit-marker-min-grade-form").show();
			$("#edit-marker-specific-grades-form").hide();
			break;
		}
		case "specificGrades": {
			$("#edit-marker-min-grade").prop("required", false);
			$("#edit-marker-min-grade-form").hide();
			$("#edit-marker-specific-grades-form").show();
			break;
		}
	}
}
$("input[type=radio][name=markerGradeType").change(function() {
	let gradesType = $(this).val();
	changeMarkerGradeType(gradesType);
})
function addVehicleToTemporaryGarage(vehicleModel, vehicleData) {
	vehicleData = vehicleData || {}
	let vehiclesTable = $("#garage-data-model-tbody")
	
	let vehiclePrimaryColor = vehicleData.primaryColor || "#111111"
	let vehicleSecondaryColor = vehicleData.secondaryColor || "#111111"
	let livery = vehicleData.livery;
	let customPlate = vehicleData.plate || "";
	let deleteVehicleBtn = $(``)
	let vehicleTableRow = $(`
		
			| ${vehicleModel} | ${vehicleModel} |  |  |  |  |  | 
	`)
	getVehicleLabel(vehicleModel, (vehicleLabel) => {
		vehicleTableRow.find(".vehicle-label").text(vehicleLabel)
	})
	vehiclesTable.append(vehicleTableRow);
	vehicleTableRow.find(".delete-vehicle-btn").append(deleteVehicleBtn)
	$(deleteVehicleBtn).click(function () {
		$(this).parents(".vehicle").remove();
	});
}
$("#garage-owned-current-coords").click(function() {
	$.post(`https://${resName}/get-current-coords`, {}, function (data) {
		var coords = data.coords;
		var heading = data.heading;
		if (coords) {
			$("#garage-owned-spawnpoint-x").val(coords.x)
			$("#garage-owned-spawnpoint-y").val(coords.y)
			$("#garage-owned-spawnpoint-z").val(coords.z)
		}
		if (heading) {
			$("#garage-owned-heading").val(heading)
		}
	})
});
function toggleBlipInputs(isEnabled) {
	$("#edit-marker-map-blip").prop("checked", isEnabled);
	$("#edit-marker-map-blip-inputs").find(".form-control").each(function() {
		$(this).prop("disabled", !isEnabled);
		$(this).prop("required", isEnabled);
	})
}
function toggleNpcInputs(isEnabled) {
	$("#edit-marker-npc").prop("checked", isEnabled);
	$("#edit-marker-npc-inputs").find(".form-control").each(function() {
		$(this).prop("disabled", !isEnabled);
		$(this).prop("required", isEnabled);
	})
}
function toggleObjectInputs(isEnabled) {
	$("#edit-marker-object").prop("checked", isEnabled);
	$("#edit-marker-object-inputs").find(".form-control").each(function() {
		$(this).prop("disabled", !isEnabled);
		$(this).prop("required", isEnabled);
	})
}
// Boss marker settings
function toggleBossWashMoneyOptions(isEnabled) {
	$("#boss-data-washmoney-percentage").prop("required", isEnabled);
	$("#boss-data-washmoney-percentage").prop("disabled", !isEnabled);
	$("#boss-data-washmoney-to-society-account").prop("disabled", !isEnabled);
}
$("#boss-data-washmoney").change(function() {
	toggleBossWashMoneyOptions( $(this).prop("checked") );
})
// Harvestable items settings
$("#harvest-item-requires-tool").change(function() {
	const isEnabled = $(this).prop("checked");
	$("#harvest-item-tool-div").find("input, button").prop("required", isEnabled).prop("disabled", !isEnabled);
	$("#harvest-item-tool-lose-on-use").prop("disabled", !isEnabled);
	if(!isEnabled) {
		$("#harvest-item-tool-lose-on-use").prop("checked", false).change();
	}
})
$("#harvest-item-tool-lose-on-use").change(function() {
	const isEnabled = $(this).prop("checked");
	$("#harvest-item-tool-lose-quantity")
		.prop("required", isEnabled)
		.prop("disabled", !isEnabled);
	$("#harvest-item-tool-lose-probability")
		.prop("required", isEnabled)
		.prop("disabled", !isEnabled);
})
$("#harvest-disappear-after-use").change(function() {
	toggleDisappearsAfterUse( $(this).prop("checked") );
	$("#harvest-disappear-seconds")
		.prop("required", isEnabled)
		.prop("disabled", !isEnabled);
})
function toggleDisappearsAfterUse(isEnabled) {
	$("#harvest-disappear-after-use").prop("checked", isEnabled);
	$("#harvest-disappear-seconds").prop("required", isEnabled);
	$("#harvest-disappear-seconds").prop("disabled", !isEnabled);
}
$("#harvest-requires-minimum-account-money").change(function() {
	let isEnabled = $(this).prop("checked");
	$("#harvest-minimum-account-name-div").find("input, button").prop("disabled", !isEnabled);
	$("#harvest-minimum-account-name-div").find("input, button").prop("required", isEnabled);
});
// Marker generic settings
$("#edit-marker-map-blip").change(function(){
	let isEnabled = $(this).prop("checked");
	toggleBlipInputs(isEnabled);
})
$("#edit-marker-npc").change(function(){
	let isEnabled = $(this).prop("checked");
	toggleNpcInputs(isEnabled);
})
$("#edit-marker-object").change(function(){
	let isEnabled = $(this).prop("checked");
	toggleObjectInputs(isEnabled);
})
$("#edit-marker-current-coords-btn").click(async function(){
	const npcModel = $("#edit-marker-npc").prop("checked") ? $("#edit-marker-npc-model").val() : null;
	const objectModel = $("#edit-marker-object") ? $("#edit-marker-object-model").val() : null;
	if(npcModel) {
		var data = await placeEntity(npcModel, "ped");
	} else if(objectModel) {	
		var data = await placeEntity(objectModel, "object");
	} else {
		var data = await placeEntity();
	}
	
	if(!data) return;
	if(npcModel || objectModel) {
		$("#edit-marker-coord-x").val(data.coords.x)
		$("#edit-marker-coord-y").val(data.coords.y)
		$("#edit-marker-coord-z").val(data.coords.z)
		
		if(npcModel) 
			$("#edit-marker-npc-heading").val(data.heading);
		if(objectModel) 
			$("#edit-marker-object-heading").val(data.heading);
	} else {
		$("#edit-marker-coord-x").val(data.x)
		$("#edit-marker-coord-y").val(data.y)
		$("#edit-marker-coord-z").val(data.z)
	}
})
$("#delete-marker-btn").click(async function(){
	let editMarkerModal = $("#edit-marker-dialog-modal");
	let markerId = editMarkerModal.data("markerId");
	editMarkerModal.modal("hide");
	if(!markerId) return;
	if(! await confirmDeletion(getLocalizedText("menu:do_you_want_to_delete_this_marker"))) return;
	const data = await $.post(`https://${resName}/delete-marker`, JSON.stringify({ markerId: markerId }))
	if (!data.isSuccessful) {
		showError(data.message);
		return
	}
	if( $("#edit-marker-form").data("isPublic") ) {
		fillPublicMarkers();
	} else {
		fillJobMarkers();
	}
})
async function getOpenExternalClothingMenu() {
	return await $.post(`https://${resName}/getOpenExternalClothingMenu`);
}
async function getInventoryScriptUsed() {
	return await $.post(`https://${resName}/getInventoryScriptUsed`);
}
async function setCurrentMarkerData(markerType, markerData) {
	// Resets animations from old opened marker
	$("#edit-marker-dialog-modal").data("animations", []);
	
	markerData = markerData || {};
	
	switch(markerType) {
		case "garage": {
			let spawnpointsDiv = $("#temporary-garage-spawnpoints-list");
			spawnpointsDiv.empty();
			if (markerData.spawnPoints) {
				markerData.spawnPoints.forEach(spawnPointData => {
					addGarageSpawnpoint(spawnpointsDiv, spawnPointData);
				})
			}
			$("#garage-data-model-tbody").empty();
			if (markerData.vehicles) {
				for (const [vehicleModel, vehicleData] of Object.entries(markerData.vehicles)) {
					addVehicleToTemporaryGarage(vehicleModel, vehicleData)
				}
			}
			break;
		}
		case "garage_buyable": {
			let spawnpointsDiv = $("#buyable-garage-spawnpoints-list");
			spawnpointsDiv.empty();
			if (markerData.spawnPoints) {
				markerData.spawnPoints.forEach(spawnPointData => {
					addGarageSpawnpoint(spawnpointsDiv, spawnPointData);
				})
			}
			$("#garage-buyable-vehicles").empty();
			if(markerData.vehicles) {
				for (const [vehicleName, price] of Object.entries(markerData.vehicles)) {
					var vehicleInputGroup = $(``)
					var vehicleInput = $(``);
					var moneySpan = $(`$`)
					var vehiclePrice = $(``);
					var deleteVehicle = $(``);
					vehicleInputGroup.append(vehicleInput, moneySpan, vehiclePrice, deleteVehicle);
					$(deleteVehicle).click(function () {
						$(this).parent().remove();
					})
					$("#garage-buyable-vehicles").append(vehicleInputGroup)
				}
			}
			
			$("#garage-buyable-vehicle-model").val("");
			$("#garage-buyable-vehicle-price").val("");
			
			break;
		}
		case "garage_owned": {
			let spawnpointsDiv = $("#owned-garage-spawnpoints-list");
			spawnpointsDiv.empty();
			if (markerData.spawnPoints) {
				markerData.spawnPoints.forEach(spawnPointData => {
					addGarageSpawnpoint(spawnpointsDiv, spawnPointData);
				})
			}
			break;
		}
		
		case "boss": {
			let canWashMoney = markerData.canWashMoney;
			let canWithdraw = markerData.canWithdraw;
			let canDeposit = markerData.canDeposit;
			let canEmployees = markerData.canEmployees;
			let canGrades = markerData.canGrades;
			toggleBossWashMoneyOptions(canWashMoney);
			if(canWashMoney) {
				$("#boss-data-washmoney-percentage").val(markerData.washMoneyReturnPercentage);
				$("#boss-data-washmoney-to-society-account").prop("checked", markerData.washMoneyGoesToSocietyAccount);
			}
			$("#boss-data-washmoney").prop('checked', canWashMoney);
			$("#boss-data-withdraw").prop('checked', canWithdraw);
			$("#boss-data-deposit").prop('checked', canDeposit);
			$("#boss-data-employees").prop('checked', canEmployees);
			$("#boss-data-grades").prop('checked', canGrades);
			
			$("#boss-data-max-salary").val(markerData.maxSalary);
			break;
		}
		case "shop": {
			setChoosenObject( $("#shop-new-item-name-div"), null );
			$("#shop-data-item-price").val("")
			$('#shop-data-items-container').empty();
			if (markerData.itemsOnSale) {
				markerData.itemsOnSale.forEach(itemData => {
					addItemToShop(itemData.object, itemData)
				})
			}
			
			break;
		}
		case "market": {
			$("#market-modal-items-tbody").empty();
			markerData?.items?.forEach(item => {
				addItemToMarket(item.object, item.minPrice, item.maxPrice, item.blackMoney, item.sellTime);
			})
			$("#market-modal-society-percentage").val(markerData.percentageForSociety);
			break;
		}
		case "crafting_table": {
			let craftablesDiv = $("#craftables");
			craftablesDiv.empty();
			if(markerData.craftablesItems) {
				markerData.craftablesItems.forEach(craftableItem => {
					addNewCraftableToCraftables(craftableItem.resultObject, craftableItem)
				})
			}
			
			break;
		}
		case "armory": {
			$("#armory-is-shared").prop("checked", markerData.isShared);
			$("#armory-refill-on-take").prop("checked", markerData.refillOnTake);
			break;
		}
		case "job_outfit": {
			$("#job-outfit-outfits").empty();
			if(!markerData.outfits) return;
			const openExternalClothingMenu = await getOpenExternalClothingMenu();
			if(openExternalClothingMenu) {
				hideAllMarkerSettings();
				$("#specific-marker-settings").hide();
				
				swal(getLocalizedText("menu:note"), getLocalizedText("menu:job_outfit_warning"), "info");
				return;
			}
			
			markerData.outfits.forEach(outfit => {
				createNewOutfit(outfit)
			})	
			break;
		}
		case "teleport": {
			if(markerData.teleportCoords) {
				$("#teleport-x").val(markerData.teleportCoords.x);
				$("#teleport-y").val(markerData.teleportCoords.y);
				$("#teleport-z").val(markerData.teleportCoords.z);
			}
			
			break;
		}
		case "harvest": {
			$("#harvest-modal-items").empty();
			
			if(markerData.harvestableItems) {
				markerData.harvestableItems.forEach(item => {
					addItemToHarvestable(item.object, item.minQuantity, item.maxQuantity, item.time, item.chances);
				});
			}
			
			if(markerData.animations) {
				$("#edit-marker-dialog-modal").data("animations", markerData.animations)
			}
			$("#harvest-item-requires-tool").prop("checked", markerData.itemTool != undefined).change();
			setChoosenObject( $("#harvest-item-tool-div"), markerData.itemTool )
			$("#harvest-item-tool-lose-on-use").prop("checked", markerData.itemToolLoseQuantity).change();
			$("#harvest-item-tool-lose-quantity").val(markerData.itemToolLoseQuantity);
			$("#harvest-item-tool-lose-probability").val(markerData.itemToolLoseProbability);
			
			toggleDisappearsAfterUse(markerData.disappearAfterUse);
			$("#harvest-disappear-seconds").val(markerData.disappearSeconds);
			$("#harvest-requires-minimum-account-money").prop("checked", markerData.requiresMinimumAccountMoney || false).change();
			$("#harvest-minimum-account-name").val(markerData.minimumAccountName);
			$("#harvest-minimum-account-amount").val(markerData.minimumAccountAmount);
			break;
		}
		case "process": {
			setChoosenObject( $("#process-modal-remove-item-div"), markerData.itemToRemove);
			$("#item-to-remove-quantity").val(markerData?.itemToRemoveQuantity || 1);
			setChoosenObject( $("#process-modal-give-item-div"), markerData.itemToAdd);
			$("#item-to-add-quantity").val(markerData?.itemToAddQuantity || 1);
			$("#process-time").val(markerData?.timeToProcess || 5);
			$("#edit-marker-dialog-modal").data("animations", markerData?.animations)
			$("#process-requires-minimum-account-money").prop("checked", markerData.requiresMinimumAccountMoney || false).change();
			$("#process-minimum-account-name").val(markerData.minimumAccountName);
			$("#process-minimum-account-amount").val(markerData.minimumAccountAmount);
			break;
		}
		case "weapon_upgrader": {
			if(markerData.componentsPrices) {
				// set empty all, so disabled components will remain disabled
				$("#weapon-upgrader-components").find(".form-control").each(function() {
					$(this).val("");
				})
				
				for(const [componentName, componentPrice] of Object.entries(markerData.componentsPrices)) {
					$("#weapon-upgrader-components").find(`[data-componentname=${componentName}]`).val(componentPrice);
				}
			}
			if(markerData.tintsPrices) {
				// set empty all, so disabled tints will remain disabled
				$("#weapon-upgrader-tints").find(".form-control").each(function() {
					$(this).val("");
				})
				for(const [tintId, tintPrice] of Object.entries(markerData.tintsPrices)) {
					$("#weapon-upgrader-tints").find(`[data-tintid=${tintId}]`).val(tintPrice);
				}
			}
			
			break;
		}
		case "job_shop": {
			let allJobsSelect = $("#job-shop-all-jobs");
			
			allJobsSelect.find(".job-shop-job").remove();
			const jobs = await $.post(`https://${resName}/getJobsData`);
			let jobsRanks = {}
			for(const [_, jobData] of Object.entries(jobs)) {
				if(jobData.name) {
					let jobDiv = $(``);
					jobsRanks[jobData.name] = jobData.ranks
					allJobsSelect.append(jobDiv);
				}
			}
			allJobsSelect.data("ranks", jobsRanks);
			
			$("#job-shop-all-jobs").val(markerData.allowedJob).change();
			$("#job-shop-all-ranks").val(markerData.minimumRank);
			break;
		} 
	}
}
function getCurrentMarkerData(markerType) {
	let markerData = {};
	switch(markerType) {
		case "garage": {		
			let vehicles = {};
			
			let vehiclesObject = $("#garage-data-model-tbody").children(".vehicle");
		
			vehiclesObject.each(function (index, element) {
				let vehicleModel = $(element).find(".vehicle-model").text();
				let vehiclePrimaryColor = $(element).find(".vehicle-primary-color").val();
				let vehicleSecondaryColor = $(element).find(".vehicle-secondary-color").val();
				let vehicleLivery = parseInt( $(element).find(".vehicle-livery").val() );
				let vehiclePlate = $(element).find(".vehicle-custom-plate").val();
		
				vehicles[vehicleModel] = {
					primaryColor: vehiclePrimaryColor,
					secondaryColor: vehicleSecondaryColor,
					livery: vehicleLivery || null,
					plate: vehiclePlate || null
				}
			})
			
			markerData = {
				vehicles: vehicles,
				spawnPoints: getGarageSpawnpoints( $("#temporary-garage-spawnpoints-list") ),
			}
			break;
		}
		case "garage_buyable": {		
			let vehicles = {};
			let vehiclesObject = $("#garage-buyable-vehicles").find(".vehicle");
	
			vehiclesObject.each(function (index, element) {
				let model = $(element).find(".vehicle-model").val();
				let price = parseInt( $(element).find(".vehicle-price").val() );
	
				vehicles[model] = price;
			});
			markerData = {
				spawnPoints: getGarageSpawnpoints( $("#buyable-garage-spawnpoints-list") ),
				vehicles: vehicles
			}
			break;
		}
		case "garage_owned": {
			markerData = {
				spawnPoints: getGarageSpawnpoints( $("#owned-garage-spawnpoints-list") ),
			}
			break;
		}
		case "boss": {
			let canWashMoney = $("#boss-data-washmoney").prop('checked')
			let canWithdraw = $("#boss-data-withdraw").prop('checked')
			let canDeposit = $("#boss-data-deposit").prop('checked')
			let canEmployees = $("#boss-data-employees").prop('checked')
			let canGrades = $("#boss-data-grades").prop('checked')
		
			if(canWashMoney) {
				var washMoneyReturnPercentage = parseInt($("#boss-data-washmoney-percentage").val());
				var washMoneyGoesToSocietyAccount = $("#boss-data-washmoney-to-society-account").prop("checked");
			}
		
			markerData = {
				canWashMoney: canWashMoney,
				washMoneyReturnPercentage: washMoneyReturnPercentage,
				washMoneyGoesToSocietyAccount: washMoneyGoesToSocietyAccount,
				canWithdraw: canWithdraw,
				canDeposit: canDeposit,
				canEmployees: canEmployees,
				canGrades: canGrades,
				maxSalary: parseInt( $("#boss-data-max-salary").val() ),
			}
			break;
		}
		case "shop": {
			let itemsOnSale = [];
			let itemsContainer = $("#shop-data-items-container")
		
			itemsContainer.children().each(function (index, element) {
				let object = $(element).data("object");
				let itemPrice = $(element).data("item-price");
				let blackMoney = $(element).find(".item-blackmoney").prop("checked");
	
				if (!object || itemPrice === undefined) return;
				itemsOnSale.push({
					object,
					price: itemPrice,
					blackMoney
				})
			})
			markerData = {
				itemsOnSale: itemsOnSale
			}
			
			break;
		}
		case "market": {
			let items = [];
			let marketBodyDiv = $("#market-modal-items-tbody")
			let itemsDivs = marketBodyDiv.children(".item")
			itemsDivs.each(function(index, element) {
				let itemDiv = $(element)
				let object = itemDiv.data("object");
				let itemMinPrice = parseInt(itemDiv.find(".item-min-price").text());
				let itemMaxPrice = parseInt(itemDiv.find(".item-max-price").text());
				let blackMoney = itemDiv.find(".item-blackmoney").prop("checked")
				let sellTime = parseInt(itemDiv.find(".item-selltime").val());
				items.push({
					object,
					minPrice: itemMinPrice,
					maxPrice: itemMaxPrice,
					blackMoney: blackMoney,
					sellTime: sellTime
				});
			});
			markerData = { 
				items: items,
				percentageForSociety: parseInt( $("#market-modal-society-percentage").val() )
			}
			break;
		}
		case "crafting_table": {
			let craftablesItems = [];
				
			$("#craftables").children().each(function(craftableIndex, craftableElement) {
				let craftable = $(craftableElement);
		
				let resultObject = getChoosenObject( craftable.find('.craftable-object-div') );
				let resultItemQuantity = parseInt( craftable.find('.result-item-quantity').val() );
				let resultItemCraftingTime = parseInt( craftable.find('.result-item-crafting-time').val() );
		
				let recipes = [];
				craftable.find('.craft-ingredients').children().each(function(ingredientIndex, ingredientElement){
					var ingredientDiv = $(ingredientElement)
		
					var ingredientObject = ingredientDiv.data("object");
					var ingredientQuantity = ingredientDiv.data("item-quantity");
					var loseOnUse = ingredientDiv.find(".lose-on-use-checkbox").prop("checked")
					
					recipes.push({
						object: ingredientObject,
						quantity: ingredientQuantity,
						loseOnUse
					});
				})
				craftablesItems.push({
					resultObject,
					recipes,
					animations: craftable.data("animations"),
					quantity: resultItemQuantity || 1,
					craftingTime: resultItemCraftingTime || 8
				});
			})
			markerData = { craftablesItems }
		
			break;
		}
		case "armory": {
			markerData = {
				isShared: $("#armory-is-shared").prop("checked"),
				refillOnTake: $("#armory-refill-on-take").prop("checked")
			}
			break;
		}
		case "job_outfit": {
			let jobOutfitsDiv = $("#job-outfit-outfits");
			let outfitsDiv = jobOutfitsDiv.children();
		
			let outfits = [];
			outfitsDiv.each(function(index, outfitDivRaw){
				let outfitDiv = $(outfitDivRaw);
	
				let outfit = getOutfitFromOutfitDiv(outfitDiv);
	
				outfits.push(outfit);
			})
	
			markerData = {
				outfits: outfits
			}
			break;
		}
		case "teleport": {
			markerData = {
				teleportCoords: {
					x: parseFloat( $(`#teleport-x`).val() ),
					y: parseFloat( $(`#teleport-y`).val() ),
					z: parseFloat( $(`#teleport-z`).val() ),
				}
			}
			break;
		}
		case "harvest": {
			let harvestableItems = [];
			$("#harvest-modal-items").find(".harvestable-item").each(function(index, element) {
				let harvestableItem = {
					object: getChoosenObject( $(this).find(".harvest-object-div") ),
					minQuantity: parseInt( $(this).find(".harvest-item-min-quantity").val() ),
					maxQuantity: parseInt( $(this).find(".harvest-item-max-quantity").val() ),
					time: parseInt( $(this).find(".harvest-item-time").val() ),
					chances: parseInt( $(this).find(".harvest-item-chance").val()),
				};
				harvestableItems.push(harvestableItem);
			})
			if($("#harvest-item-requires-tool").prop("checked")) {
				var itemTool = getChoosenObject( $("#harvest-item-tool-div") );
			}
			if($("#harvest-item-tool-lose-on-use").prop("checked")) {
				var itemToolLoseQuantity = parseInt($("#harvest-item-tool-lose-quantity").val());
				var itemToolLoseProbability = parseInt( $("#harvest-item-tool-lose-probability").val() );
			}
			markerData = {
				harvestableItems,
				animations: $("#edit-marker-dialog-modal").data("animations"),
				itemTool,
				itemToolLoseQuantity,
				itemToolLoseProbability,
				disappearAfterUse: $("#harvest-disappear-after-use").prop("checked"),
				disappearSeconds: parseInt( $("#harvest-disappear-seconds").val() ),
				requiresMinimumAccountMoney: $("#harvest-requires-minimum-account-money").prop("checked"),
				minimumAccountName: $("#harvest-minimum-account-name").val(),
				minimumAccountAmount: parseInt( $("#harvest-minimum-account-amount").val() ),
			}
			break;
		}
		case "process": {
			markerData = {
				itemToRemove: getChoosenObject( $("#process-modal-remove-item-div") ),
				itemToRemoveQuantity: parseInt($("#item-to-remove-quantity").val()),
				itemToAdd: getChoosenObject( $("#process-modal-give-item-div") ),
				itemToAddQuantity: parseInt($("#item-to-add-quantity").val()),
				timeToProcess: parseInt($("#process-time").val()),
				animations: $("#edit-marker-dialog-modal").data("animations"),
				requiresMinimumAccountMoney: $("#process-requires-minimum-account-money").prop("checked"),
				minimumAccountName: $("#process-minimum-account-name").val(),
				minimumAccountAmount: parseInt( $("#process-minimum-account-amount").val() )
			}
			break;
		}
		case "weapon_upgrader": {
			let weaponsComponentsDiv = $("#weapon-upgrader-components");
			let weaponsTintsDiv = $("#weapon-upgrader-tints");
			
			let componentsPrices = {};
			let tintsPrices = {};
			weaponsComponentsDiv.find(".form-control").each(function(index, element) {
				let componentDiv = $(element)
				let componentName = componentDiv.data("componentname")
				let componentPrice = componentDiv.val()
				if(componentPrice) {
					componentsPrices[componentName] = componentPrice
				}
			})
			weaponsTintsDiv.find(".form-control").each(function(index, element) {
				let tintDiv = $(element)
				let tintId = parseInt(tintDiv.data("tintid"))
				let tintPrice = parseInt(tintDiv.val())
				if(tintPrice) {
					tintsPrices[tintId] = tintPrice
				}
			})
			markerData = {
				componentsPrices: componentsPrices,
				tintsPrices: tintsPrices
			}
			
			break;
		}
		case "job_shop": {
			let jobName = $("#job-shop-all-jobs").val();
			if(!jobName) return;
			let rankGrade = parseInt($("#job-shop-all-ranks").val());
			
			if(jobName && !isNaN(rankGrade)) {
				markerData = {
					allowedJob: jobName,
					minimumRank: rankGrade
				}
			}
			
			break;
		}
	}
	return markerData;
}
$("#edit-marker-form").submit(function(event){
	if (!this.checkValidity()) {
		event.stopPropagation();
		event.preventDefault();
		return;
	}
	let editMarkerModal = $("#edit-marker-dialog-modal");
	let markerId = editMarkerModal.data("markerId");
	let isPublicMarker = $("#edit-marker-form").data("isPublic");
	let enableMarkerBlip = $("#edit-marker-map-blip").prop("checked");
	if(enableMarkerBlip) {
		var blipSpriteId = 	parseInt( $("#edit-marker-sprite-id").val() );
		var blipColor = 	parseInt( $("#edit-marker-blip-color").val() );
		var blipScale = 	parseFloat( $("#edit-marker-blip-scale").val() );
	}
	let color = hexToRgb( $("#edit-marker-color").val() );
	let enableNPC = $("#edit-marker-npc").prop("checked");
	if(enableNPC) {
		var npcModel = $("#edit-marker-npc-model").val();
		var npcHeading = parseFloat( $("#edit-marker-npc-heading").val() );
	}
	let enableObject = $("#edit-marker-object").prop("checked");
	if(enableObject) {
		var objectModel = $("#edit-marker-object-model").val();
	}
	let gradesType = $("input[type=radio][name=markerGradeType]:checked").val();
	if(gradesType === "minimumGrade") {
		var minGrade = parseInt( $("#edit-marker-min-grade").val() );
	} else if(gradesType === "specificGrades") {
		var specificGrades = $("#edit-marker-specific-grades").data("grades") || {};
	}
	let data = {
		markerId: markerId,
		label: $("#edit-marker-label").val(),
		gradesType: gradesType,
		minGrade: minGrade,
		specificGrades: specificGrades,
		coords: {
			x: parseFloat( $("#edit-marker-coord-x").val() ),
			y: parseFloat( $("#edit-marker-coord-y").val() ),
			z: parseFloat( $("#edit-marker-coord-z").val() ),
		},
		blip: {
			spriteId: blipSpriteId,
			color: blipColor,
			scale: blipScale,
		},
		
		markerType: parseInt( $("#edit-marker-type").val() ),
		scale: {
			x: parseFloat( $("#edit-marker-scale-x").val() ),
			y: parseFloat( $("#edit-marker-scale-y").val() ),
			z: parseFloat( $("#edit-marker-scale-z").val() )
		},
		
		color: {
			r: color.r,
			g: color.g,
			b: color.b,
			alpha: parseInt( $("#edit-marker-alpha").val() )
		},
		ped: {
			model: npcModel,
			heading: npcHeading
		},
		object: {
			model: objectModel,
			heading: parseFloat( $("#edit-marker-object-heading").val() )
		}
	}
	let markerData = getCurrentMarkerData(allMarkers[markerId].type);
	$.post(`https://${resName}/update-marker`, JSON.stringify(data), function (data) {
		if (data.isSuccessful) {
			let markerType = allMarkers[markerId].type
			if(MARKERS_INFOS[markerType].requiresDataUpdate) {
				$.post(`https://${resName}/update-marker-data`, JSON.stringify({ markerId: markerId, markerData: markerData }), function (data) {
					if (data.isSuccessful) {
						editMarkerModal.modal("hide");
					} else {
						showError(data.message)
					}
	
					if(isPublicMarker) {
						fillPublicMarkers();
					} else {
						fillJobMarkers();
					}
				});
			} else {
				editMarkerModal.modal("hide");
				if(isPublicMarker) {
					fillPublicMarkers();
				} else {
					fillJobMarkers();
				}
			}
		} else {
			showError(data.message)
		}
	})
})
function gradesDialog(enabledGrades) {
	return new Promise(resolve => {
		let gradesModal = $("#input-grades-dialog-modal")
		let gradesList = $("#grades-list");
		gradesList.empty();
	
		let jobName = $("#edit-job").data("jobName");
	
		$.post(`https://${resName}/getJobGrades`, JSON.stringify({jobName: jobName}), function(jobGrades) {
			for( const[_, gradeData] of Object.entries(jobGrades) ) {
				let gradeDiv = $(`
					
						
						
					
				`);
	
				gradesList.append(gradeDiv);
			}
	
			gradesModal.modal("show");
		})
		
	
		let confirmButton = $("#input-grades-dialog-confirm");
		
		confirmButton.unbind("click");
		confirmButton.click(function() {
			let grades = {};
			$(".grade:checked").each(function() {
				grades[ parseInt($(this).val()) ] = true;
			})
	
			gradesModal.modal("hide");
	
			resolve(grades);		
		})
	});
}
function setSpecificGrades(grades) {
	let specificGradesDiv = $("#edit-marker-specific-grades");
	
	specificGradesDiv.data("grades", grades);
	specificGradesDiv.val( Object.keys(grades).join(","));
}
$("#edit-marker-specific-grades-choose-btn").click(async function() {
	let enabledGrades = $("#edit-marker-specific-grades").data("grades") || {};
	let grades = await gradesDialog(enabledGrades);
	setSpecificGrades(grades);
})
$("#marker-data-add-vehicle").click(function () {
	var modelDiv = $("#marker-data-vehicle-model");
	var model = modelDiv.val();
	// Clears input
	modelDiv.val("");
	if (model) {
		modelDiv.removeClass("is-invalid");
		addVehicleToTemporaryGarage(model)
	} else {
		modelDiv.addClass("is-invalid");
	}
})
function getGarageSpawnpoints(listDiv) {
	let spawnpoints = [];
	listDiv.find(".spawnpoint-div").each(function() {
		let spawnpointData = {
			coords: {
				x: parseFloat( $(this).find(".spawnpoint-coords-x").val() ),
				y: parseFloat( $(this).find(".spawnpoint-coords-y").val() ),
				z: parseFloat( $(this).find(".spawnpoint-coords-z").val() ),
			},
			heading: parseFloat( $(this).find(".spawnpoint-heading").val() ),	
			radius: parseInt( $(this).find(".spawnpoint-radius").val() )
		}
		spawnpoints.push(spawnpointData);
	})
	return spawnpoints;
}
function addGarageSpawnpoint(listDiv, spawnpointData) {
	let div = $(`
		
				
			Coords
			
			
			
			Heading
				
									
			Radius
				
		
	`);
	div.find(".delete-spawnpoint-btn").click(function() {
		div.remove();
	});
	div.find(".current-coords-btn").click(async function() {
		const data = await getCurrentCoordsAndHeading();
		div.find(".spawnpoint-coords-x").val(data.coords.x);
		div.find(".spawnpoint-coords-y").val(data.coords.y);
		div.find(".spawnpoint-coords-z").val(data.coords.z);
		div.find(".spawnpoint-heading").val(data.heading);
	});
			
	if(spawnpointData) {
		div.find(".spawnpoint-coords-x").val(spawnpointData.coords.x);
		div.find(".spawnpoint-coords-y").val(spawnpointData.coords.y);
		div.find(".spawnpoint-coords-z").val(spawnpointData.coords.z);
		div.find(".spawnpoint-heading").val(spawnpointData.heading);
		div.find(".spawnpoint-radius").val(spawnpointData.radius);
	}
	listDiv.append(div);
}
$("#temporary-garage-add-spawnpoint").click(function() {
	addGarageSpawnpoint( $("#temporary-garage-spawnpoints-list") );
})
$("#buyable-garage-add-spawnpoint").click(function() {
	addGarageSpawnpoint( $("#buyable-garage-spawnpoints-list") );
})
$("#owned-garage-add-spawnpoint").click(function() {
	addGarageSpawnpoint( $("#owned-garage-spawnpoints-list") );
})
function addItemToShop(object, itemData) {
	var newItem = $(`
		
			| ${object.name} | $${itemData.price} | 
					
				 |  | 
	`)
	newItem.data("item-price", parseInt(itemData.price));
	newItem.find(".item-blackmoney").prop("checked", itemData.blackMoney);
	newItem.find(".btn").click(function () { newItem.remove(); })
	newItem.data("object", object);
	$('#shop-data-items-container').append(newItem)
}
$("#shop-data-add-btn").click(function () {
	var isEverythingValid = true
	let choosenObject = getChoosenObject( $("#shop-new-item-name-div") );
	var itemPriceDiv = $("#shop-data-item-price")
	var itemName = choosenObject.name;
	var itemPrice = itemPriceDiv.val();
	let itemData = {
		price: itemPrice
	}
	if (!itemName) return;
	if (!itemPrice) {
		itemPriceDiv.addClass("is-invalid")
		isEverythingValid = false
	} else {
		itemPriceDiv.removeClass("is-invalid")
	}
	if (!isEverythingValid) return;
	addItemToShop(choosenObject, itemData);
})
$("#garage-buyable-add-vehicle").click(function () {
	var isEverythingValid = true;
	
	var modelDiv = $("#garage-buyable-vehicle-model");
	var model = modelDiv.val();
	var priceDiv = $("#garage-buyable-vehicle-price");
	var price = parseInt(priceDiv.val());
	// Clears input
	modelDiv.val("");
	priceDiv.val("");
	if (model) {
		modelDiv.removeClass("is-invalid");
	} else {
		modelDiv.addClass("is-invalid");
		isEverythingValid = false
	}
	if(price) {
		priceDiv.removeClass("is-invalid")
	} else {
		priceDiv.addClass("is-invalid")
		isEverythingValid = false
	}
	if(isEverythingValid) {
		var vehicleInputGroup = $(``)
		var vehicleInput = $(``);
		var moneySpan = $(`$`)
		var vehiclePrice = $(``);
		var deleteVehicle = $(``);
		vehicleInputGroup.append(vehicleInput, moneySpan, vehiclePrice, deleteVehicle);
		$(deleteVehicle).click(function () {
			$(this).parent().remove();
		})
		$("#garage-buyable-vehicles").append(vehicleInputGroup)
	}
})
$("#garage-buyable-current-coords").click(function() {
	$.post(`https://${resName}/get-current-coords`, {}, function (data) {
		var coords = data.coords;
		var heading = data.heading;
		if (coords) {
			$("#garage-buyable-spawnpoint-x").val(coords.x)
			$("#garage-buyable-spawnpoint-y").val(coords.y)
			$("#garage-buyable-spawnpoint-z").val(coords.z)
		}
		if (heading) {
			$("#garage-buyable-heading").val(heading)
		}
	})
})
function addNewCraftableToCraftables(object, craftingData) {
	var craftablesDiv = $("#craftables");
	var newCraftable = $(`
		
			
			
				
					
						| ${getLocalizedText("menu:dynamic:marker:crafting_table:item_id")} | ${getLocalizedText("menu:dynamic:marker:crafting_table:item_quantity")} | ${getLocalizedText("menu:dynamic:marker:crafting_table:lose_on_use")} | ${getLocalizedText("menu:dynamic:marker:crafting_table:remove")} | 
				
				
				
			
			
			
				
				
			
			
		 
	`)
	loadChooseObjectDivs( newCraftable.find(".craftable-object-div"), object)
	loadChooseObjectDivs( newCraftable.find(".ingredient-object-div"))
	newCraftable.find(".remove-craft-btn").click(function() {
		newCraftable.remove();
	})
	newCraftable.find(".animations-craft-btn").click(function() {
		inputAnimations(newCraftable.data("animations"), function(animations) {
			newCraftable.data("animations", animations)
		});
	})
	var addToCraftBtn = newCraftable.find(".add-to-craft-btn")
	addToCraftBtn.click(function() {
		var itemQuantityDiv = newCraftable.find(".crafting-table-item-quantity");
		const object = getChoosenObject( newCraftable.find(".ingredient-object-div") );
		var itemQuantity = parseInt( itemQuantityDiv.val() );
		if(!object) return;
		if(!itemQuantity || itemQuantity <= 0) {
			itemQuantityDiv.addClass("is-invalid");
			return;
		} else {
			itemQuantityDiv.removeClass("is-invalid");
		}
		var craftIngredientsDiv = newCraftable.find(".craft-ingredients");
		let newCraftItem = $(`
			
				| ${object.name} | ${itemQuantity} | 
						
					 |  | 
		`)
		newCraftItem.data("object", object);
		newCraftItem.find('.remove-ingredient-btn').click(function() {
			newCraftItem.remove()
		})
		craftIngredientsDiv.append(newCraftItem)
		setChoosenObject( newCraftable.find(".ingredient-object-div"), null )
		itemQuantityDiv.val("");
	})
	if(craftingData?.recipes) {
		let craftIngredientsDiv = newCraftable.find('.craft-ingredients');
		
		craftingData.recipes.forEach(ingredientData => {
			let newCraftItem = $(`
				
					| ${ingredientData.object.name} | ${ingredientData.quantity} | 
							
						 |  | 
			`)
			newCraftItem.data("object", ingredientData.object);
			let loseOnUse = ingredientData.loseOnUse
			newCraftItem.find(".lose-on-use-checkbox").prop("checked", loseOnUse)
			newCraftItem.find('.remove-ingredient-btn').click(function() {
				newCraftItem.remove()
			})
			craftIngredientsDiv.append(newCraftItem);
		})
	}
	newCraftable.data("animations", craftingData?.animations || undefined)
	craftablesDiv.append(newCraftable);
}
$("#crafting-table-new-craft-btn").click(function() {
	addNewCraftableToCraftables()
})
$("#delete-armory-content").click(async function(){
	let armoryModal = $("#armory-data-modal");
	
	let markerId = armoryModal.data("markerId")
	
	armoryModal.modal("hide");
	if(! await confirmDeletion(getLocalizedText("menu:do_you_want_to_delete_armory_content"))) return;
	const data = $.post(`https://${resName}/delete-armory-inventory`, JSON.stringify({ markerId: markerId }));
	if(!data.isSuccessful) {
		showError(data.message)
	}
})
$("#delete-stash-inventory").click(async function() {
	let editMarkerModal = $("#edit-marker-dialog-modal");
	let markerId = editMarkerModal.data("markerId");
	if(! await confirmDeletion(getLocalizedText("menu:do_you_want_to_delete_stash_content"))) return;
	const data = await $.post(`https://${resName}/delete-stash-inventory`, JSON.stringify({ markerId: markerId }));
	if(!data.isSuccessful) {
		showError(data.message)
	}
})
function createNewOutfit(outfit){
	outfit = outfit || {};
	outfit.tshirt_1 = outfit.tshirt_1 || 0;
	outfit.tshirt_2 = outfit.tshirt_2 || 0;
	outfit.torso_1 = outfit.torso_1 || 0;
	outfit.torso_2 = outfit.torso_2 || 0;
	outfit.decals_1 = outfit.decals_1 || 0;
	outfit.decals_2 = outfit.decals_2 || 0;
	outfit.arms = outfit.arms || 0;
	outfit.arms_2 = outfit.arms_2 || 0;
	outfit.pants_1 = outfit.pants_1 || 0;
	outfit.pants_2 = outfit.pants_2 || 0;
	outfit.shoes_1 = outfit.shoes_1 || 0;
	outfit.shoes_2 = outfit.shoes_2 || 0;
	outfit.mask_1 = outfit.mask_1 || 0;
	outfit.mask_2 = outfit.mask_2 || 0;
	outfit.bproof_1 = outfit.bproof_1 || 0;
	outfit.bproof_2 = outfit.bproof_2 || 0;
	outfit.chain_1 = outfit.chain_1 || 0;
	outfit.chain_2 = outfit.chain_2 || 0;
	outfit.helmet_1 = outfit.helmet_1 || -1;
	outfit.helmet_2 = outfit.helmet_2 || 0;
	outfit.glasses_1 = outfit.glasses_1 || 0;
	outfit.glasses_2 = outfit.glasses_2 || 0;
	outfit.bags_1 = outfit.bags_1 || 0;
	outfit.bags_2 = outfit.bags_2 || 0;
	let outfitsDiv = $("#job-outfit-outfits")
	let outfitId = $("#job-outfit-outfits").children().length + 1;
	
	let outfitDiv = $(`
		
			
				
				
					
						
						
						
					 
				 
			 
		 
	`)
	outfitDiv.find(".current-outfit-btn").click(function(){
		$.post(`https://${resName}/get-current-outfit`, JSON.stringify({}), function (data) {
			outfitDiv.find(".outfit-tshirt").val(data.tshirt_1)
			outfitDiv.find(".outfit-tshirt-color").val(data.tshirt_2)
			outfitDiv.find(".outfit-torso").val(data.torso_1)
			outfitDiv.find(".outfit-torso-color").val(data.torso_2)
			outfitDiv.find(".outfit-decals").val(data.decals_1)
			outfitDiv.find(".outfit-decals-color").val(data.decals_2)
			outfitDiv.find(".outfit-arms").val(data.arms)
			outfitDiv.find(".outfit-arms-color").val(data.arms_2)
			outfitDiv.find(".outfit-pants").val(data.pants_1)
			outfitDiv.find(".outfit-pants-color").val(data.pants_2)
			outfitDiv.find(".outfit-shoes").val(data.shoes_1)
			outfitDiv.find(".outfit-shoes-color").val(data.shoes_2)
			outfitDiv.find(".outfit-mask").val(data.mask_1)
			outfitDiv.find(".outfit-mask-color").val(data.mask_2)
			outfitDiv.find(".outfit-bulletproof").val(data.bproof_1)
			outfitDiv.find(".outfit-bulletproof-color").val(data.bproof_2)
			outfitDiv.find(".outfit-chain").val(data.chain_1)
			outfitDiv.find(".outfit-chain-color").val(data.chain_2)
			outfitDiv.find(".outfit-helmet").val(data.helmet_1)
			outfitDiv.find(".outfit-helmet-color").val(data.helmet_2)
			outfitDiv.find(".outfit-glasses").val(data.glasses_1)
			outfitDiv.find(".outfit-glasses-color").val(data.glasses_2)
			outfitDiv.find(".outfit-bag").val(data.bags_1)
			outfitDiv.find(".outfit-bag-color").val(data.bags_2)
		});
	})
	outfitDiv.find(".delete-outfit-btn").click(async function(){
		if(! await confirmDeletion(getLocalizedText("menu:do_you_want_to_delete_outfit"))) return;
		outfitDiv.remove();
	})
	$(outfitsDiv).append(outfitDiv)
}
function getOutfitFromOutfitDiv(outfitDiv) {
	let outfit = {}
	outfit.label = outfitDiv.data("label")
	outfit.tshirt_1 = parseInt(outfitDiv.find(".outfit-tshirt").val()) || 0;
	outfit.tshirt_2 = parseInt(outfitDiv.find(".outfit-tshirt-color").val()) || 0;
	outfit.torso_1 = parseInt(outfitDiv.find(".outfit-torso").val()) || 0;
	outfit.torso_2 = parseInt(outfitDiv.find(".outfit-torso-color").val()) || 0;
	outfit.decals_1 = parseInt(outfitDiv.find(".outfit-decals").val()) || 0;
	outfit.decals_2 = parseInt(outfitDiv.find(".outfit-decals-color").val()) || 0;
	outfit.arms = parseInt(outfitDiv.find(".outfit-arms").val()) || 0;
	outfit.arms_2 = parseInt(outfitDiv.find(".outfit-arms-color").val()) || 0;
	outfit.pants_1 = parseInt(outfitDiv.find(".outfit-pants").val()) || 0;
	outfit.pants_2 = parseInt(outfitDiv.find(".outfit-pants-color").val()) || 0;
	outfit.shoes_1 = parseInt(outfitDiv.find(".outfit-shoes").val()) || 0;
	outfit.shoes_2 = parseInt(outfitDiv.find(".outfit-shoes-color").val()) || 0;
	outfit.mask_1 = parseInt(outfitDiv.find(".outfit-mask").val()) || 0;
	outfit.mask_2 = parseInt(outfitDiv.find(".outfit-mask-color").val()) || 0;
	outfit.bproof_1 = parseInt(outfitDiv.find(".outfit-bulletproof").val()) || 0;
	outfit.bproof_2 = parseInt(outfitDiv.find(".outfit-bulletproof-color").val()) || 0;
	outfit.chain_1 = parseInt(outfitDiv.find(".outfit-chain").val()) || 0;
	outfit.chain_2 = parseInt(outfitDiv.find(".outfit-chain-color").val()) || 0;
	outfit.helmet_1 = parseInt(outfitDiv.find(".outfit-helmet").val()) || -1;
	outfit.helmet_2 = parseInt(outfitDiv.find(".outfit-helmet-color").val()) || 0
	outfit.glasses_1 = parseInt(outfitDiv.find(".outfit-glasses").val()) || 0;
	outfit.glasses_2 = parseInt(outfitDiv.find(".outfit-glasses-color").val()) || 0;
	outfit.bags_1 = parseInt(outfitDiv.find(".outfit-bag").val()) || 0;
	outfit.bags_2 = parseInt(outfitDiv.find(".outfit-bag-color").val()) || 0;
	return outfit;
}
$("#job-outfit-new-outfit-btn").click(function(){
	inputDialog("Create new outfit", [
		{ id: "outfitLabel", label: "New outfit label:" },
	], function (data) {
		let outfit = {label: data.outfitLabel}
		createNewOutfit(outfit);
	});
})
$("#teleport-current-coords-btn").click(function(){
	$.post(`https://${resName}/get-current-coords`, {}, function (data) {
		var coords = data.coords;
		if (coords) {
			$(`#teleport-x`).val(coords.x)
			$(`#teleport-y`).val(coords.y)
			$(`#teleport-z`).val(coords.z)
		}
	})
});
function addItemToMarket(object, itemMinPrice, itemMaxPrice, blackMoney = false, sellTime = 0) {
	let itemsTableDiv = $("#market-modal-items-tbody");
	let itemDiv = $(`
		
			| ${object.name} | ${itemMinPrice} | ${itemMaxPrice} |  |  |  | 
	`)
	let deleteBtn = $(``);
	deleteBtn.click(function(){ itemDiv.remove(); })
	itemDiv.find(".delete-btn").append(deleteBtn);
	
	itemDiv.find(".item-blackmoney").prop("checked", blackMoney);
	itemDiv.data("object", object);
	itemsTableDiv.append(itemDiv);
}
$("#market-modal-new-item-btn").click(function(){
	let itemIdDiv = $("#market-modal-new-item-name-input");
	const chooseObjectDiv = $("#market-new-item-name-div");
	let object = getChoosenObject(chooseObjectDiv);
	let itemMinPriceDiv = $("#market-modal-new-item-min-price-input");
	let itemMaxPriceDiv = $("#market-modal-new-item-max-price-input");
	let itemMinPrice = itemMinPriceDiv.val();
	let itemMaxPrice = itemMaxPriceDiv.val();
	if(object) {
		itemIdDiv.removeClass("is-invalid");
	} else {
		itemIdDiv.addClass("is-invalid");
	}
	if(itemMinPrice) {
		itemMinPriceDiv.removeClass("is-invalid");
	} else {
		itemMinPriceDiv.addClass("is-invalid");
	}
	if(itemMaxPrice) {
		itemMaxPriceDiv.removeClass("is-invalid");
	} else {
		itemMaxPriceDiv.addClass("is-invalid");
	}
	if(object && itemMinPrice && itemMaxPrice) {
		setChoosenObject(chooseObjectDiv, null);
		itemMinPriceDiv.val("");
		itemMaxPriceDiv.val("");
		addItemToMarket(object, itemMinPrice, itemMaxPrice);
	}
})
function inputAnimations(animations, cb) {
	let animationsModal = $("#animations-modal");
	let animationsForm = $("#animations-modal-form");
	$("#animations").empty();
	if(animations && animations.length > 0) {
		animations.forEach(animation => {
			addAnimation(animation)
		})
	} else {
		addAnimation();
	}
	animationsForm.unbind();
	animationsForm.submit(function(event) {
		if (!this.checkValidity()) {
			event.stopPropagation();
			event.preventDefault();
			return;
		} else {
			$(animationsForm).removeClass("was-validated");
		}
		let animations = [];
		$("#animations").find(".animation-container").each(function() {
			let currentAnimDiv = $(this);
			let animType = currentAnimDiv.find(".animation-type").prop("checked");
			// If it's a scenario
			if(animType) {
				animations.push({
					type: "scenario",
					scenarioName: currentAnimDiv.find(".scenario-name").val(),
					scenarioDuration: parseInt(currentAnimDiv.find(".scenario-duration").val())
				})
			} else { // If it's an animation
				animations.push({
					type: "animation",
					animDict: currentAnimDiv.find(".animation-dictionary").val(),
					animName: currentAnimDiv.find(".animation-name").val(),
					animDuration: parseInt(currentAnimDiv.find(".animation-duration").val())
				})
			}
		})
		animationsModal.modal("hide");
		cb(animations)
	})
	animationsModal.modal("show");
}
function addAnimation(animation) {
	if(!animation) {
		animation = {};
	}
	let fullAnimContainer = $(`
		
	`);
	let scenarioContainer = fullAnimContainer.find(".scenario");
	let animationContainer = fullAnimContainer.find(".animation");
	let switchLabel = fullAnimContainer.find(".animation-type-label");
	let switchInput = fullAnimContainer.find(".animation-type");
	let removeAnimBtn = fullAnimContainer.find(".remove-anim-btn");
	fullAnimContainer.find(".animation-type").change(function() {
		let isChecked = $(this).prop("checked");
		if(isChecked) {
			scenarioContainer.show();
			scenarioContainer.find(".form-control").prop("required", true);
			animationContainer.hide();
			animationContainer.find(".form-control").prop("required", false);
			switchLabel.text("Scenario");
		} else {
			scenarioContainer.hide();
			scenarioContainer.find(".form-control").prop("required", false);
			animationContainer.show();
			animationContainer.find(".form-control").prop("required", true);
			switchLabel.text("Animation");
		}
	})
	removeAnimBtn.click(function() {
		$(this).parent().remove();
	})
	if(animation && animation.type == "scenario") {
		switchInput.prop("checked", true).trigger("change");
	}
	$("#animations").append(fullAnimContainer);
}
$("#add-animation-btn").click(function(){
	addAnimation();
})
$("#harvest-add-item-btn").click(function() {
	addItemToHarvestable();
});
$("#harvest-animations-btn").click(function() {
	let editMarkerModal = $("#edit-marker-dialog-modal");
	inputAnimations(editMarkerModal.data("animations"), function(animations) {
		editMarkerModal.data("animations", animations)
	});
});
$("#harvest-disappear-after-use").change(function(){
	toggleDisappearsAfterUse( $(this).prop("checked") );
});
$("#harvest-choose-account-btn").click(function() {
	accountsDialog(accountName => {
		$("#harvest-minimum-account-name").val(accountName);
	})
})
function addItemToHarvestable(object, minQuantity = "", maxQuantity = "", secondsToHarvest = "", chances = "") {
	var itemDiv = $(`
	
	`);
	$(itemDiv).find(".remove-harvestable-item-btn").click(function() {
		$(this).parents(".harvestable-item").remove();
	})
	loadChooseObjectDivs( $(itemDiv).find(".choose-object-div"), object);
	$("#harvest-modal-items").append(itemDiv);
}
$("#process-animations-btn").click(function() {
	let editMarkerModal = $("#edit-marker-dialog-modal");
	inputAnimations(editMarkerModal.data("animations"), function(animations) {
		editMarkerModal.data("animations", animations)
	});
})
$("#process-requires-minimum-account-money").change(function() {
	let isEnabled = $(this).prop("checked");
	$("#process-minimum-account-name-div").find("input, button").prop("disabled", !isEnabled);
	$("#process-minimum-account-name-div").find("input, button").prop("required", isEnabled);
});
$("#process-choose-account-btn").click(function() {
	accountsDialog(accountName => {
		$("#process-minimum-account-name").val(accountName);
	})
})
$("#job-shop-all-jobs").change(function() {
	let jobRanks = $(this).data("ranks");
	let jobName = $(this).val();
	let allRanksSelect = $("#job-shop-all-ranks");
	allRanksSelect.find(".job-shop-rank").remove();
	let ranksArray = Array.isArray(jobRanks[jobName]) ? jobRanks[jobName] : Object.values(jobRanks[jobName]);
	ranksArray.forEach(rank => {
		let rankDiv = $(``);
		allRanksSelect.append(rankDiv);
	})
})
function loadAllJobsOnlinePlayers() {
	$.post(`https://${resName}/getAllJobsOnlinePlayers`, {}, function(jobsOnlinePlayers) {
		allJobsStatisticsChart.data.labels = [];
		allJobsStatisticsChart.data.datasets[0] = {};
		allJobsStatisticsChart.data.datasets[0].data = [];
		allJobsStatisticsChart.data.datasets[0].label = getLocalizedText("menu:online_players");
		allJobsStatisticsChart.data.datasets[0].backgroundColor = "rgba(26, 188, 156, 0.5)";
		allJobsStatisticsChart.data.datasets[0].borderColor = "rgba(26, 188, 156, 0.8)";
		allJobsStatisticsChart.data.datasets[0].borderWidth = 1;
		allJobsStatisticsChart.options.scales.y.ticks.callback = function(value, index, values) {
			if (Number.isInteger(value)) { return value; } 
		}
		let maximumValue = 0;
		jobsOnlinePlayers.forEach(jobData => {
			allJobsStatisticsChart.data.labels.push(jobData.label);
			allJobsStatisticsChart.data.datasets[0].data.push(jobData.playersCount);
			if (jobData.playersCount > maximumValue) {
				maximumValue = jobData.playersCount;
			}
		});
		allJobsStatisticsChart.options.scales.y.suggestedMax = maximumValue + 1;
		allJobsStatisticsChart.update();
	});
}
function loadAllJobsTotalPlayers() {
	$.post(`https://${resName}/getAllJobsTotalPlayers`, {}, function(jobsTotalPlayers) {
		allJobsStatisticsChart.data.labels = [];
		allJobsStatisticsChart.data.datasets[0] = {};
		allJobsStatisticsChart.data.datasets[0].data = [];
		allJobsStatisticsChart.data.datasets[0].label = getLocalizedText("menu:total_players");
		allJobsStatisticsChart.data.datasets[0].backgroundColor = "rgba(26, 188, 156, 0.5)";
		allJobsStatisticsChart.data.datasets[0].borderColor = "rgba(26, 188, 156, 0.8)";
		allJobsStatisticsChart.data.datasets[0].borderWidth = 1;
		allJobsStatisticsChart.options.scales.y.ticks.callback = function(value, index, values) {
			if (Number.isInteger(value)) { return value; } 
		}
		let maximumValue = 0;
		jobsTotalPlayers.forEach(jobData => {
			allJobsStatisticsChart.data.labels.push(jobData.label);
			allJobsStatisticsChart.data.datasets[0].data.push(jobData.playersCount);
			if (jobData.playersCount > maximumValue) {
				maximumValue = jobData.playersCount;
			}
		});
		allJobsStatisticsChart.options.scales.y.suggestedMax = maximumValue + 1;
		allJobsStatisticsChart.update();
	});
}
function loadAllJobsSocietyMoney() {
	$.post(`https://${resName}/getJobsSocietyMoney`, {}, function(jobsSocietyMoney) {
		allJobsStatisticsChart.data.labels = [];
		allJobsStatisticsChart.data.datasets[0] = {};
		allJobsStatisticsChart.data.datasets[0].data = [];
		allJobsStatisticsChart.data.datasets[0].label = getLocalizedText("menu:society_money");
		allJobsStatisticsChart.data.datasets[0].backgroundColor = "rgba(241, 196, 15, 0.4)";
		allJobsStatisticsChart.data.datasets[0].borderColor = "rgba(241, 196, 15, 0.8)";
		allJobsStatisticsChart.data.datasets[0].borderWidth = 1;
		allJobsStatisticsChart.options.scales.y.ticks.callback = function(value, index, values) {
			return "$" + value;
		}
		let maximumValue = 0;
		jobsSocietyMoney.forEach(jobData => {
			allJobsStatisticsChart.data.labels.push(jobData.label);
			allJobsStatisticsChart.data.datasets[0].data.push(jobData.money);
			if (jobData.money > maximumValue) {
				maximumValue = jobData.money;
			}
		});
		allJobsStatisticsChart.options.scales.y.suggestedMax = maximumValue + maximumValue * 0.10;
		allJobsStatisticsChart.update();
	});
}
$('input[type=radio][name=all-jobs-statistics-type]').change(function() {
    let action = $(this).val();
	switch(action) {
		case "online-players": {
			loadAllJobsOnlinePlayers();
			break;
		}
		case "total-players": {
			loadAllJobsTotalPlayers();
			break;
		}
		case "society-money": {
			loadAllJobsSocietyMoney();
			break;
		}
	}
});
function loadRanksDistrubutions(){
	let jobName = $("#edit-job").data("jobName");
	$.post(`https://${resName}/getRanksDistribution`, JSON.stringify({jobName: jobName }), function(rankDistribution) {
		jobStatisticsChart.data.labels = [];
		jobStatisticsChart.data.datasets[0] = {};
		jobStatisticsChart.data.datasets[0].data = [];
		jobStatisticsChart.data.datasets[0].label = getLocalizedText("menu:chart:players_in_rank");
		jobStatisticsChart.data.datasets[0].backgroundColor = "rgba(26, 188, 156, 0.5)";
		jobStatisticsChart.data.datasets[0].borderColor = "rgba(26, 188, 156, 0.8)";
		jobStatisticsChart.data.datasets[0].borderWidth = 1;
		jobStatisticsChart.options.scales.y.ticks.callback = function(value, index, values) {
			if (Number.isInteger(value)) { return value; } 
		}
		
		let maximumValue = 0;
		rankDistribution.forEach(rankData => {
			jobStatisticsChart.data.labels.push(rankData.label);
			jobStatisticsChart.data.datasets[0].data.push(rankData.playersCount);
			if (rankData.playersCount > maximumValue) {
				maximumValue = rankData.playersCount;
			}
		});
		jobStatisticsChart.options.scales.y.suggestedMax = maximumValue + 1;
		jobStatisticsChart.update();
	})
}
async function settingsTour() {
	const introName = "settingsTour";
	if(await hasIntroBeenViewed(introName)) return;
	const tour = new Shepherd.Tour({
		useModalOverlay: true,
		defaultStepOptions: {
			scrollTo: true
		}
	});
	tour.addStep({
		text: getLocalizedText("menu:intro:settings"),
		attachTo: {
			element: '#settings',
			on: 'right'
		},
		buttons: [
			{
				text: getLocalizedText("menu:intro:skip"),
				action: tour.cancel,
				secondary: true
			},
			{
				text: getLocalizedText("menu:intro:next"),
				action: tour.next
			}
		]
	});
	tour.addStep({
		text: getLocalizedText("menu:intro:settings_external_names"),
		attachTo: {
			element: '#settings-external-scripts-names',
			on: 'right'
		},
		buttons: [
			{
				text: getLocalizedText("menu:intro:skip"),
				action: tour.cancel,
				secondary: true
			},
			{
				text: getLocalizedText("menu:intro:next"),
				action: tour.next
			}
		]
	});
	tour.addStep({
		text: getLocalizedText("menu:intro:settings_modules"),
		attachTo: {
			element: '#settings-modules',
			on: 'right'
		},
		buttons: [
			{
				text: getLocalizedText("menu:intro:skip"),
				action: tour.cancel,
				secondary: true
			},
			{
				text: getLocalizedText("menu:intro:next"),
				action: tour.next
			}
		]
	});
	tour.start();
	registerIntroView(introName);
}
$("#settings-tab").click(settingsTour);
async function jobTour() {
	const introName = "jobTour";
	if(await hasIntroBeenViewed(introName)) return;
	const tour = new Shepherd.Tour({
		useModalOverlay: true,
		defaultStepOptions: {
			scrollTo: true
		}
	});
	tour.addStep({
		text: getLocalizedText("menu:intro:ranks"),
		attachTo: {
			element: '#create-rank-btn',
			on: 'left'
		},
		buttons: [
			{
				text: getLocalizedText("menu:intro:skip"),
				action: tour.cancel,
				secondary: true
			},
			{
				text: getLocalizedText("menu:intro:next"),
				action: tour.next
			}
		]
	});
	
	tour.addStep({
		text: getLocalizedText("menu:intro:job_settings"),
		attachTo: {
			element: '#job-settings-tab',
			on: 'right'
		},
		buttons: [
			{
				text: getLocalizedText("menu:intro:skip"),
				action: tour.cancel,
				secondary: true
			},
			{
				text: getLocalizedText("menu:intro:okay"),
				action: tour.next
			}
		]
	});
	tour.start();
	registerIntroView(introName);
}
async function mainMenuTour() {
	const introName = "mainMenuTour";
	if(await hasIntroBeenViewed(introName)) return;
	const tour = new Shepherd.Tour({
		useModalOverlay: true,
		defaultStepOptions: {
			scrollTo: true
		}
	});
	tour.addStep({
		text: getLocalizedText("menu:intro:welcome"),
		buttons: [
			{
				text: getLocalizedText("menu:intro:skip"),
				action: tour.cancel,
				secondary: true
			},
			{
				text: getLocalizedText("menu:intro:next"),
				action: tour.next
			}
		]
	});
	tour.addStep({
		text: getLocalizedText("menu:intro:jobs"),
		attachTo: {
			element: '#create-job-btn',
			on: 'left'
		},
		buttons: [
			{
				text: getLocalizedText("menu:intro:skip"),
				action: tour.cancel,
				secondary: true
			},
			{
				text: getLocalizedText("menu:intro:next"),
				action: tour.next
			}
		]
	});
	tour.addStep({
		text: getLocalizedText("menu:intro:jobs_table"),
		attachTo: {
			element: '#jobs-container',
			on: 'right'
		},
		buttons: [
			{
				text: getLocalizedText("menu:intro:skip"),
				action: tour.cancel,
				secondary: true
			},
			{
				text: getLocalizedText("menu:intro:next"),
				action: tour.next
			}
		]
	});
	tour.addStep({
		text: getLocalizedText("menu:intro:public_markers"),
		attachTo: {
			element: '#public-markers-tab',
			on: 'right'
		},
		buttons: [
			{
				text: getLocalizedText("menu:intro:skip"),
				action: tour.cancel,
				secondary: true
			},
			{
				text: getLocalizedText("menu:intro:okay"),
				action: tour.next
			}
		]
	});
	tour.start();
	registerIntroView(introName);
}
// [[ NEXUS ]]
const voteJobRater = raterJs({
	starSize: 35,
	element: document.querySelector("#vote-job-rater"),
	rateCallback: async function rateCallback(rating, done) {
		const jobId = $("#nexus-modal").data("jobInstance").id;
		const success = await $.post(`https://${resName}/nexus/rateJob`, JSON.stringify({rating, jobId}));
		if(success) voteJobRater.setRating(rating);
		done();
	}
});
const averageJobVotes = raterJs({
	starSize: 20,
	readOnly: true,
	element: document.querySelector("#nexus-modal-job-average-rating"),
});
$("#nexus-import-job-btn").click(async function() {
	const jobId = $("#nexus-modal").data("jobInstance").id;
	const response = await $.post(`https://${resName}/nexus/importJob`, JSON.stringify({jobId}));
	$("#nexus-modal").modal("hide");
	if(response === true) refresh();
	showServerResponse(response);
});
let nexusDataTable = $("#nexus-jobs-container").DataTable({
	"lengthMenu": [5, 10, 15, 20],
	"pageLength": 10,
	"order": [[3, 'desc'], [4, 'desc']],
	"createdRow": function (row, data, index) {
		$(row).addClass("clickable");
		$(row).click(function () {
			const jobInstance = $(this).data("jobInstance");
			showJobInstance(jobInstance);
			$("#nexus-modal").modal("show");
		});
	},
	"columnDefs": [{ "defaultContent": "???", "targets": "_all" }]
});
  
function showJobInstance(jobInstance) {
	$("#nexus-modal").data("jobInstance", jobInstance);
	$("#nexus-modal-job-listing-label").text(jobInstance.label);
	$("#nexus-modal-job-label").text(jobInstance.jobConfiguration.label);
	$("#nexus-modal-job-name").text(jobInstance.jobConfiguration.name);
	$("#nexus-modal-job-description").text(jobInstance.description || getLocalizedText("menu:nexus:no_description"));
	$("#nexus-modal-job-author").text(jobInstance.author);
	// Votes
	if(jobInstance?.votes?.total > 0) {
		averageJobVotes.setRating(jobInstance?.votes.averageRating);
	} else {
		averageJobVotes.setRating(0);
	}
	$("#nexus-modal-job-total-votes").text(jobInstance.votes?.total || 0);
	// This server vote
	voteJobRater.setRating(0);
	// Actions
	const actionsListDiv = $("#nexus-modal-job-actions-list");
	actionsListDiv.empty();
	let currentRow = null;
	for(let i=0; i < ACTIONS_LABELS.length; i++) {
		const {action, label} = ACTIONS_LABELS[i];
		const actionValue = jobInstance.jobConfiguration.actions[action];
		const isEnabled = action == "placeableObjects" ? actionValue.length > 0 : actionValue;
		if(i % 2 === 0) {
			actionsListDiv.append(currentRow);
			currentRow = null;
		}
		const emoji = isEnabled ? "✅" : "❌";
		if(currentRow == null) currentRow = $("");
		
		currentRow.append( i % 2 !== 0 ? `${label} ${emoji}` : `${emoji} ${label}`);
	}
	if (currentRow !== null) actionsListDiv.append(currentRow);
	// Ranks
	const ranksListDiv = $("#nexus-modal-job-ranks-list");
	ranksListDiv.empty();
	for(const [rank, rankInfo] of Object.entries(jobInstance.jobConfiguration.ranks)) {
		const rankDiv = $(`
			
				${rankInfo.label}
				${rank}
			
		`);
		ranksListDiv.append(rankDiv);
	}
	// Markers count
	const markersCount = jobInstance.jobMarkers ? Object.keys(jobInstance.jobMarkers).length : 0;
	$("#nexus-modal-job-included-markers-count").text(markersCount);
}
$("#upload-job-to-nexus-btn").click(async function() {
	const jobName = await singleJobDialog();
	if(!jobName) return;
	$("#nexus-modal-upload").data("jobName", jobName);
	$("#nexus-upload-label").val("");
	$("#nexus-upload-description").val("");
	$("#nexus-upload-include-job-markers").prop("checked", true).change();
	$("#nexus-upload-accept-tos").prop("checked", false)
	$("#nexus-upload-accept-sharing-data").prop("checked", false)
	
	const allJobs = await $.post(`https://${resName}/getJobsData`);
	const jobData = allJobs[jobName];
	$("#nexus-upload-label-shared-job-label").val(jobData.label)
	$("#nexus-upload-label-shared-job-id").val(jobData.name)
	const jobMarkers = await $.post(`https://${resName}/retrieveJobMarkers`, JSON.stringify({jobName}));
	$("#nexus-upload-included-markers-count").val(Object.keys(jobMarkers).length)
	$("#nexus-modal-upload").modal("show");
});
$("#nexus-upload-include-job-markers").change(function() {
	const isChecked = $(this).prop("checked");
	$("#nexus-upload-included-markers-count-div").toggle(isChecked);
});
$("#nexus-upload-form").submit(async function(event) {
	if(isThereAnyErrorInForm(event)) return;
	const dataToUpload = {
		jobName: $("#nexus-modal-upload").data("jobName"),
		label: $("#nexus-upload-label").val(),
		description: $("#nexus-upload-description").val(),
		includeJobMarkers: $("#nexus-upload-include-job-markers").prop("checked"),
	}
	const result = await $.post(`https://${resName}/nexus/uploadJob`, JSON.stringify(dataToUpload));
	if(result == true) {
		swal("Success", getLocalizedText("menu:nexus:upload_success"), "success");
		resetNexus();
	} else {
		swal("Error", result, "error");
	}
	$("#nexus-modal-upload").modal("hide");
});
$("#enter-in-nexus-btn").click(async function() {
	$("#nexus-login").find(".spinner-border").show();
	$("#enter-in-nexus-label").text("...");
	const jobs = await $.get(`https://${resName}/nexus/getJobs`);
	if(!jobs) {
		swal("Error", getLocalizedText("menu:nexus:not_available"), "error");
		resetNexus();
		return;
	} 
	
	nexusDataTable.clear();
	for(const[_, jobInstance] of Object.entries(jobs)) {
		const roundedAverageRating = jobInstance?.votes?.averageRating ? Math.round(jobInstance.votes.averageRating) : 0;
		const ratingStars = jobInstance?.votes?.total ? "⭐".repeat(roundedAverageRating) : getLocalizedText("menu:nexus:not_rated");
		const limitedDescription = jobInstance.description?.length > 30 ? jobInstance.description.substring(0, 30) + "..." : jobInstance.description;
		const jobMarkersCount = jobInstance.jobMarkers ? Object.keys(jobInstance.jobMarkers).length : 0;
		const rawRow = nexusDataTable.row.add( [jobInstance.label, limitedDescription, jobMarkersCount, ratingStars, jobInstance.votes?.total || 0, jobInstance.author] );
		const rowDiv = $(rawRow.node());
		$(rowDiv).data("jobInstance", jobInstance);
	}
	nexusDataTable.draw();
	$("#nexus-login").hide();
	$("#nexus-container").show();
})
function resetNexus() {
	$("#nexus-login").show();
	$("#nexus-login").find(".spinner-border").hide();
	$("#enter-in-nexus-label").text("Enter in Nexus");
	$("#nexus-container").hide();
}
async function init(version, fullConfig) {
	$("#job-creator-version").text(version);
	loadSettings(fullConfig);
	resetNexus()
	$("#job-creator").show();
	
	await refresh();
	mainMenuTour();
	refreshAnnouncements();
}
function exit() {
	// Resets current active tab (jobs is the default one)
	$("#job-creator").find(".nav-link, .tab-pane").each(function() {
		if($(this).data("isDefault") == "1") {
			$(this).addClass(["active", "show"])
		} else {
			$(this).removeClass(["active", "show"])
		}
	})
	$("#job-creator").hide();
	$.post(`https://${resName}/exit`)
}
window.addEventListener('message', (event) => {
	let data = event.data;
	let action = data.action;
	if (action == 'show') {
		init(data.version, data.fullConfig);
	}
})
$("#close-main-btn").click(function () {
	exit()
})
/*
 
░██████╗███████╗████████╗████████╗██╗███╗░░██╗░██████╗░░██████╗
██╔════╝██╔════╝╚══██╔══╝╚══██╔══╝██║████╗░██║██╔════╝░██╔════╝
╚█████╗░█████╗░░░░░██║░░░░░░██║░░░██║██╔██╗██║██║░░██╗░╚█████╗░
░╚═══██╗██╔══╝░░░░░██║░░░░░░██║░░░██║██║╚████║██║░░╚██╗░╚═══██╗
██████╔╝███████╗░░░██║░░░░░░██║░░░██║██║░╚███║╚██████╔╝██████╔╝
╚═════╝░╚══════╝░░░╚═╝░░░░░░╚═╝░░░╚═╝╚═╝░░╚══╝░╚═════╝░╚═════╝░
*/
function addJobInWhitelistForOffDutyJobs(jobName) {
	const listDiv = $("#settings_whitelistForOffdutyJobs");
	listDiv.append(`
		
			${jobName}
			
		
	`);
	listDiv.find(".remove-job").click(function() {
		$(this).parent().remove();
	});
}
$("#settings_addNewWhitelistedJobForOffduty").click(function() {
	let inputDiv = $("#settings_newWhitelistedJobForOffduty");
	let jobName = inputDiv.val();
	if(!jobName) return;
	
	inputDiv.val("");
	addJobInWhitelistForOffDutyJobs(jobName);
});
function getWhitelistedJobsForOffduty() {
	let jobs = {};
	$("#settings_whitelistForOffdutyJobs").find(".job").each(function() {
		let jobName = $(this).data("jobName");
		jobs[jobName] = true;
	});
	return jobs;
}
function clearLicensesInList(type) {
	if(type === "driver") {
		var listDiv = $("#settings_drivingLicensesList");
	} else if(type === "weapon") {
		var listDiv = $("#settings_weaponLicensesList");
	}
	if(listDiv) {
		listDiv.empty();
	}
}
function addNewLicenseInList(licenseName, type) {
	if(type === "driver") {
		var listDiv = $("#settings_drivingLicensesList");
	} else if(type === "weapon") {
		var listDiv = $("#settings_weaponLicensesList");
	}
	if(listDiv) {
		listDiv.append(`
			
				${licenseName}
				
			
		`);
		listDiv.find(".remove-license").click(function() {
			$(this).parent().remove();
		});
	}
}
$("#settings_addNewDrivingLicenseBtn").click(function() {
	let drivingLicenseName = $("#settings_newDrivingLicense").val();
	
	if(drivingLicenseName) {
		$("#settings_newDrivingLicense").val("");
		addNewLicenseInList(drivingLicenseName, "driver");
	}
})
$("#settings_addNewWeaponLicenseBtn").click(function() {
	let weaponLicenseName = $("#settings_newWeaponLicense").val();
	
	if(weaponLicenseName) {
		$("#settings_newWeaponLicense").val("");
		addNewLicenseInList(weaponLicenseName, "weapon");
	}
})
function getSettingsLicenses(type) {
	if(type === "driver") {
		var listDiv = $("#settings_drivingLicensesList");
	} else if(type === "weapon") {
		var listDiv = $("#settings_weaponLicensesList");
	}
	let licenses = {};
	listDiv.find(".license").each(function(index, element) {
		licenses[ $(element).data("license") ] = true;
	})
	return licenses;
}
function getSeparatedDiscordWebhooks() {
	let webhooks = {};
	$("#settings_specific_webhooks").find(".form-control").each(function(index, element) {
		let markerType = $(element).data("markerType");
		let webhook = $(element).val();
		if(webhook) {
			webhooks[markerType] = webhook;
		}
	});
	return webhooks;
}
$("#settings").submit(async function(event) {
	if(isThereAnyErrorInForm(event)) return;
	let clientSettings = {
		markerDistance: parseFloat( $("#settings_markerDistance").val() ),
		use3Dtext: $("#settings_use3Dtext").prop("checked"),
		textSize: parseInt( $("#settings_textSize").val() ),
		textFont: parseInt( $("#settings_textFont").val() ),
		carLockpickTime: parseInt( $("#settings_carLockpickTime").val() ),
		enableAlarmWhenLockpicking: $("#settings_enableAlarmWhenLockpicking").prop("checked"),
		useJSFourIdCard: $("#settings_useJSFourIdCard").prop("checked"),
		canUseActionsMenuWhileOffDuty: $("#settings_canUseActionsMenuWhileOffDuty").prop("checked"),
		licenses: {
			driver: getSettingsLicenses("driver"),
			weapon: getSettingsLicenses("weapon"),
		},
		marketSellOnePerTime: $("#settings_marketSellOnePerTime").prop("checked"),
		menuPosition: $("#settings_menuPosition").val(),
		actionsMenuKey: $("#settings_actionsMenuKey").val(),
		freezeWhenSoftHandcuffed: $("#settings_freezeWhenSoftHandcuffed").prop("checked"),
		freezeWhenHardHandcuffed: $("#settings_freezeWhenHardHandcuffed").prop("checked"),
		searchRequiresHandcuffState: $("#settings_searchRequiresHandcuffState").prop("checked"),
		targetingScript:$("#settings-targeting-script").val(),
		whitelistedControlsWhileHandcuffed: getAllWhitelistedControlsWhileHandcuffed(),
		toggleDrag: {
			enabled: $("#toggle-drag-enabled").prop("checked"),
			key: $("#toggle-drag-default-key").val()
		}
	}
	let sharedSettings = {
		allowAfkFarming: $("#settings_allowAfkFarming").prop("checked"),
		locale: $("#settings_locale").val(),
		externalScriptsNames: getIntegrationSettings(),
		modules: getModulesSettings(),
		handcuffsEnableSelfRelease: $("#settings_handcuffsEnableSelfRelease").prop("checked"),
	}
	let serverSettings = {
		unemployedJob: $("#settings_unemployedJob").val(),
		unemployedGrade: parseInt( $("#settings_unemployedGrade").val() ),
		acePermission: $("#settings_acePermission").val(),
		areDiscordLogsActive: $("#settings_isDiscordLogActive").prop("checked"),
		mainDiscordWebhook: $("#settings_discordWebhook").val(),
		specificWebhooks: getSeparatedDiscordWebhooks(),
		handcuffRequireItem: $("#settings_handcuffRequireItem").prop("checked"),
		handcuffsItemName: $("#settings_handcuffsItemName").val(),
		handcuffsRemoveOnUse: $("#settings_handcuffsRemoveOnUse").prop("checked"),
		lockpickCarRequireItem: $("#settings_lockpickCarRequireItem").prop("checked"),
		lockpickItemName: $("#settings_lockpickItemName").val(),
		lockpickRemoveOnUse: $("#settings_lockpickRemoveOnUse").prop("checked"),
		robbableAccounts: getRobbableAccounts(),
		canAlwaysCarryItem: $("#settings_canAlwaysCarryItem").prop("checked"),
		depositableInSafeAccounts: getDepositableInSafeAccounts(),
		repairVehicleRequireItem: $("#settings_repairVehicleRequireItem").prop("checked"),
		repairVehicleItemName: $("#settings_repairVehicleItemName").val(),
		repairVehicleRemoveOnUse: $("#settings_repairVehicleRemoveOnUse").prop("checked"),
		cleanVehicleRequireItem: $("#settings_cleanVehicleRequireItem").prop("checked"),
		cleanVehicleItemName: $("#settings_cleanVehicleItemName").val(),
		cleanVehicleRemoveOnUse: $("#settings_cleanVehicleRemoveOnUse").prop("checked"),
		healRequireItem: $("#settings_healRequireItem").prop("checked"),
		healItemName: $("#settings_healItemName").val(),
		healRemoveOnUse: $("#settings_healRemoveOnUse").prop("checked"),
		
		reviveRequireItem: $("#settings_reviveRequireItem").prop("checked"),
		reviveItemName: $("#settings_reviveItemName").val(),
		reviveRemoveOnuse: $("#settings_reviveRemoveOnUse").prop("checked"),
		enablePropertyOutfits: $("#settings_enablePropertyOutfits").prop("checked"),
		parkAllOwnedVehiclesOnRestart: $("#settings_parkAllOwnedVehiclesOnRestart").prop("checked"),
		
		whitelistedJobsForOffduty: getWhitelistedJobsForOffduty(),
		blackMoney: getBlackMoneySettings(),
	}
	const response = await $.post(`https://${resName}/saveSettings`, JSON.stringify({
		clientSettings: clientSettings,
		serverSettings: serverSettings,
		sharedSettings: sharedSettings
	}));
	showServerResponse(response);
	refreshTranslations(sharedSettings.locale);
})
async function toggleDiscordLogsInSettings(enable) {
	$("#settings_discordWebhook").prop("disabled", !enable);
	$("#settings_discordWebhook").prop("required", enable);
	
	$("#settings_specific_webhooks").find(`.form-control`).prop("disabled", !enable);
	if(await getInventoryScriptUsed() !== "default" || await getFramework() !== "ESX") {
		$("#settings_specific_webhooks").find(`.form-control[data-marker-type="stash"]`).prop("disabled", true);
		$("#settings_specific_webhooks").find(`.form-control[data-marker-type="armory"]`).prop("disabled", true);
		$("#settings_specific_webhooks").find(`.form-control[data-marker-type="safe"]`).prop("disabled", true);
	}
}
$("#settings_isDiscordLogActive").change(function() {
	let enabled = $(this).prop("checked");
	toggleDiscordLogsInSettings(enabled);
})
$(`input[type=radio][name=black-money-worth-type]`).change(function() {
	const worthType = $(this).val();
	const isMetadata = worthType === "metadata";
	$("#settings-black-money-metadata-field-id-div").toggle(isMetadata);
	$("#settings-black-money-metadata-field-id").prop("required", isMetadata);
});
function setBlackMoneySettings(blackMoney) {
	$(`input[type=radio][name=black-money-worth-type][value=${blackMoney.worthType}]`).prop("checked", true).change();
	setChoosenObject( $("#settings-choose-black-money-div"), blackMoney.object);
	$("#settings-black-money-metadata-field-id").val(blackMoney.metadataFieldId);
}
function getBlackMoneySettings() {
	return {
		worthType: $(`input[type=radio][name=black-money-worth-type]:checked`).val(),
		object: getChoosenObject( $("#settings-choose-black-money-div") ),
		metadataFieldId: $("#settings-black-money-metadata-field-id").val()
	}
}
async function loadSettings(fullConfig) {
	// CLIENT
	$("#settings_markerDistance").val(fullConfig.markerDistance);
	// 3D Text
	$("#settings_use3Dtext").prop("checked", fullConfig.use3Dtext);
	$("#settings_textSize").val(fullConfig.textSize);
	setTomSelectValue("#settings_textFont", fullConfig.textFont)
	
	// Targeting
	setTomSelectValue("#settings-targeting-script", fullConfig.targetingScript)
	// Black money
	setBlackMoneySettings(fullConfig.blackMoney);
	// Car lockpicking
	$("#settings_carLockpickTime").val(fullConfig.carLockpickTime);
	$("#settings_enableAlarmWhenLockpicking").prop("checked", fullConfig.enableAlarmWhenLockpicking);
	$("#settings_useJSFourIdCard").prop("checked", fullConfig.useJSFourIdCard);
	$("#settings_canUseActionsMenuWhileOffDuty").prop("checked", fullConfig.canUseActionsMenuWhileOffDuty);
	$("#settings_marketSellOnePerTime").prop("checked", fullConfig.marketSellOnePerTime);
	// Whitelisted jobs for off duty
	$("#off-duty-jobs-whitelist").toggle( await getFramework() == "ESX" );
	$("#settings_whitelistForOffdutyJobs").empty();
	for(const jobName of Object.keys(fullConfig.whitelistedJobsForOffduty || {})) {
		addJobInWhitelistForOffDutyJobs(jobName)
	}
	// Weapon/Driving licenses
	if(fullConfig.licenses) {
		for(const[licenseType, licenses] of Object.entries(fullConfig.licenses)) {
			clearLicensesInList(licenseType);
			Object.keys(licenses).forEach(licenseName => {
				addNewLicenseInList(licenseName, licenseType);
			})
		}
	}
	// Menu position
	setTomSelectValue("#settings_menuPosition", fullConfig.menuPosition)
	// Actions key
	$("#settings_actionsMenuKey").val(fullConfig.actionsMenuKey);
	loadIntegrationsSettings(fullConfig.externalScriptsNames);
	loadModulesSettings(fullConfig.modules);
	// SHARED
	$("#settings_allowAfkFarming").prop("checked", fullConfig.allowAfkFarming);
	setTomSelectValue("#settings_locale", fullConfig.locale)
	// Generic
	$("#settings_unemployedJob").val(fullConfig.unemployedJob);
	$("#settings_unemployedGrade").val(fullConfig.unemployedGrade);
	$("#settings_acePermission").val(fullConfig.acePermission);
	// Discord logs webhooks
	$("#settings_isDiscordLogActive").prop("checked", fullConfig.areDiscordLogsActive);
	toggleDiscordLogsInSettings(fullConfig.areDiscordLogsActive);
	$("#settings_discordWebhook").val(fullConfig.mainDiscordWebhook);
	// Handcuffs
	toggleSettingsHandcuffsRequireItem(fullConfig.handcuffRequireItem);
	$("#settings_handcuffsItemName").val(fullConfig.handcuffsItemName)
	$("#settings_handcuffsRemoveOnUse").prop("checked", fullConfig.handcuffsRemoveOnUse)
	$("#settings_handcuffsEnableSelfRelease").prop("checked", fullConfig.handcuffsEnableSelfRelease);
	$("#settings_freezeWhenSoftHandcuffed").prop("checked", fullConfig.freezeWhenSoftHandcuffed);
	$("#settings_freezeWhenHardHandcuffed").prop("checked", fullConfig.freezeWhenHardHandcuffed);
	// Whitelisted controls while handcuffed
	$("#whitelisted-controls-while-handcuffed-list").empty();
	fullConfig.whitelistedControlsWhileHandcuffed.forEach(control => {
		addWhitelistedControlWhileHandcuffed(control);
	})
	// Toggle drag
	$("#toggle-drag-enabled").prop("checked", fullConfig.toggleDrag.enabled);
	$("#toggle-drag-default-key").val(fullConfig.toggleDrag.key);
	// Search
	$("#settings_searchRequiresHandcuffState").prop("checked", fullConfig.searchRequiresHandcuffState);
	// Lockpick
	toggleSettingsLockpickRequireItem(fullConfig.lockpickCarRequireItem);
	$("#settings_lockpickItemName").val(fullConfig.lockpickItemName)
	$("#settings_lockpickRemoveOnUse").prop("checked", fullConfig.lockpickRemoveOnUse)
	// Vehicle repair
	toggleSettingsVehicleRepairRequireItem(fullConfig.repairVehicleRequireItem);
	$("#settings_repairVehicleItemName").val(fullConfig.repairVehicleItemName);
	$("#settings_repairVehicleRemoveOnUse").prop("checked", fullConfig.repairVehicleRemoveOnUse);
	// Vehicle cleaning
	toggleSettingsVehicleCleaningRequireItem(fullConfig.cleanVehicleRequireItem);
	$("#settings_cleanVehicleItemName").val(fullConfig.cleanVehicleItemName);
	$("#settings_cleanVehicleRemoveOnUse").prop("checked", fullConfig.cleanVehicleRemoveOnUse);
	// Healing
	toggleSettingsHealingRequireItem(fullConfig.healRequireItem);
	$("#settings_healItemName").val(fullConfig.healItemName);
	$("#settings_healRemoveOnUse").prop("checked", fullConfig.healRemoveOnUse);
	// Reviving
	toggleSettingsRevivingRequireItem(fullConfig.reviveRequireItem);
	$("#settings_reviveItemName").val(fullConfig.reviveItemName);
	$("#settings_reviveRemoveOnUse").prop("checked", fullConfig.reviveRemoveOnuse);
	// Robbable accounts
	$("#settings_robbableAccountsList").empty();
	if(fullConfig.robbableAccounts) {
		fullConfig.robbableAccounts.forEach(account => {
			addNewRobbableAccountInList(account)
		});
	}
	$("#settings_canAlwaysCarryItem").prop("checked", fullConfig.canAlwaysCarryItem);
	// Depositable accounts
	$("#settings_depositableAccountsList").empty();
	if(fullConfig.depositableInSafeAccounts) {
		fullConfig.depositableInSafeAccounts.forEach(account => {
			addNewDepositableAccountInList(account)
		});
	}
	$("#settings_enablePropertyOutfits").prop("checked", fullConfig.enablePropertyOutfits);
	$("#settings_parkAllOwnedVehiclesOnRestart").prop("checked", fullConfig.parkAllOwnedVehiclesOnRestart);
	for(const[markerType, webhook] of Object.entries(fullConfig.specificWebhooks)) {
		$("#settings_specific_webhooks").find(`[data-marker-type="${markerType}"]`).val(webhook);
	}
}
$("#settingsRestoreDefaultBtn").click(async function() {
	if(! await confirmDeletion(getLocalizedText("menu:are_you_sure_to_restore_settings"))) return;
	const defaultConfiguration = await $.post(`https://${resName}/getDefaultConfiguration`);
	loadSettings(defaultConfiguration);
})
function addNewRobbableAccountInList(accountName) {
	var listDiv = $("#settings_robbableAccountsList");
	if(listDiv) {
		listDiv.append(`
			
				${accountName}
				
			
		`);
		listDiv.find(".remove-account").click(function() {
			$(this).parent().remove();
		});
	}
}
$("#settings_addNewRobbableAccountBtn").click(function() {
	let robbableAccount = $("#settings_newRobbableAccount").val();
	
	if(robbableAccount) {
		$("#settings_newRobbableAccount").val("");
		addNewRobbableAccountInList(robbableAccount);
	}
})
function getRobbableAccounts() {
	var listDiv = $("#settings_robbableAccountsList");
	let robbableAccounts = [];
	listDiv.find(".robbable-account").each(function(index, element) {
		robbableAccounts.push( $(element).data("account") );
	})
	return robbableAccounts;
}
function addNewDepositableAccountInList(accountName) {
	var listDiv = $("#settings_depositableAccountsList");
	if(listDiv) {
		listDiv.append(`
			
				${accountName}
				
			
		`);
		listDiv.find(".remove-account").click(function() {
			$(this).parent().remove();
		});
	}
}
$("#settings_addNewDepositableAccountBtn").click(function() {
	let depositableAccount = $("#settings_newDepositableAccount").val();
	
	if(depositableAccount) {
		$("#settings_newDepositableAccount").val("");
		addNewDepositableAccountInList(depositableAccount);
	}
})
function getDepositableInSafeAccounts() {
	var listDiv = $("#settings_depositableAccountsList");
	let depositableAccounts = [];
	listDiv.find(".depositable-account").each(function(index, element) {
		depositableAccounts.push( $(element).data("account") );
	})
	return depositableAccounts;
}
// Handcuffs settings
function toggleSettingsHandcuffsRequireItem(enable) {
	$("#settings_handcuffRequireItem").prop("checked", enable);
	$("#settings_handcuffsItemName").prop("disabled", !enable);
	$("#settings_handcuffsItemName").prop("required", enable);
	$("#settings_handcuffsRemoveOnUse").prop("disabled", !enable);
}
$("#settings_handcuffRequireItem").change(function() {
	toggleSettingsHandcuffsRequireItem( $("#settings_handcuffRequireItem").prop("checked") );
})
function getAllWhitelistedControlsWhileHandcuffed() {
	let controls = [];
	$("#whitelisted-controls-while-handcuffed-list").find(".control-btn").each(function(index, element) {
		const controlNumber = parseInt( $(element).val() );
		if(controlNumber) controls.push(controlNumber);
	})
	return controls;
}
function addWhitelistedControlWhileHandcuffed(control="") {
	const div = $(`
	
	`);
	div.find(".btn-close").click(function() {
		div.remove();
	});
	div.find(".control-btn").click(async function() {
		const controlNumber = await controlsDialog();
		if(!controlNumber) return;
		$(this).val(controlNumber);
	});
	$("#whitelisted-controls-while-handcuffed-list").append(div);
}
$("#add-whitelisted-control-while-handcuffed-btn").click(function() {
	addWhitelistedControlWhileHandcuffed();
})
// Lockpick settings
function toggleSettingsLockpickRequireItem(enable) {
	$("#settings_lockpickCarRequireItem").prop("checked", enable);
	$("#settings_lockpickItemName").prop("disabled", !enable);
	$("#settings_lockpickItemName").prop("required", enable);
	$("#settings_lockpickRemoveOnUse").prop("disabled", !enable);
}
$("#settings_lockpickCarRequireItem").change(function() {
	toggleSettingsLockpickRequireItem( $(this).prop("checked") );
})
// Vehicle repair settings
function toggleSettingsVehicleRepairRequireItem(enable) {
	$("#settings_repairVehicleRequireItem").prop("checked", enable);
	$("#settings_repairVehicleItemName").prop("disabled", !enable);
	$("#settings_repairVehicleItemName").prop("required", enable);
	$("#settings_repairVehicleRemoveOnUse").prop("disabled", !enable);
}
$("#settings_repairVehicleRequireItem").change(function() {
	toggleSettingsVehicleRepairRequireItem( $(this).prop("checked") );
})
// Vehicle cleaning settings
function toggleSettingsVehicleCleaningRequireItem(enable) {
	$("#settings_cleanVehicleRequireItem").prop("checked", enable);
	$("#settings_cleanVehicleItemName").prop("disabled", !enable);
	$("#settings_cleanVehicleItemName").prop("required", enable);
	$("#settings_cleanVehicleRemoveOnUse").prop("disabled", !enable);
}
$("#settings_cleanVehicleRequireItem").change(function() {
	toggleSettingsVehicleCleaningRequireItem( $(this).prop("checked") );
})
// Healing settings
function toggleSettingsHealingRequireItem(enable) {
	$("#settings_healRequireItem").prop("checked", enable);
	$("#settings_healItemName").prop("disabled", !enable);
	$("#settings_healItemName").prop("required", enable);
	$("#settings_healRemoveOnUse").prop("disabled", !enable);
}
$("#settings_healRequireItem").change(function() {
	toggleSettingsHealingRequireItem( $(this).prop("checked") );
})
// Reviving settings
function toggleSettingsRevivingRequireItem(enable) {
	$("#settings_reviveRequireItem").prop("checked", enable);
	$("#settings_reviveItemName").prop("disabled", !enable);
	$("#settings_reviveItemName").prop("required", enable);
	$("#settings_reviveRemoveOnUse").prop("disabled", !enable);
}
$("#settings_reviveRequireItem").change(function() {
	toggleSettingsRevivingRequireItem( $(this).prop("checked") );
})
// Closes menu when clicking ESC
$(document).on('keyup', function(e) {
	if (e.key == "Escape") {
		if( $("#job-creator").is(":visible") ) {
			exit();
		} else if( $("#edit-job").is(":visible") ) {
			exitFromEditJob();
		}
	}
});