`);
	div.find(".btn-close").click(function() {
		div.remove();
	});
	div.find(".choose-item-btn").click(async function() {
		let objectType = div.find(".item-type").val();
		let objectName = await objectDialog(objectType);
		div.find(".item-name").val(objectName);
	});
	if(rewardItem) {
		div.find(".item-type").val(rewardItem.type);
		div.find(".item-name").val(rewardItem.name);
		div.find(".item-min-quantity").val(rewardItem.minQuantity);
		div.find(".item-max-quantity").val(rewardItem.maxQuantity);
		div.find(".item-chances").val(rewardItem.chances);
	}
	listDiv.append(div);
}
function createDivForRewardItemsList(rewardItems=[], rewardMinAmount, rewardMaxAmount) {
	const div = $(`
		
			${getLocalizedText("menu:reward_items")} 
			
			
			${getLocalizedText("menu:no_elements_added")}
			
				${getLocalizedText("menu:add_object")} 
			
	`);
	// Activate tooltips
	div.find("[data-bs-toggle=tooltip]").tooltip();
	div.find(".add-reward-item-btn").click(function() {
		addRewardItemInList(div.find(".reward-items-list"));
	});
	rewardItems.forEach(function(rewardItem) {
		addRewardItemInList(div.find(".reward-items-list"), rewardItem);
	});
	return div;
}
function getRewardItemsFromDiv(div) {
	let rewardItems = [];
	div.find(".reward-item").each(function() {
		let rewardItem = {
			type: $(this).find(".item-type").val(),
			name: $(this).find(".item-name").val(),
			minQuantity: parseInt( $(this).find(".item-min-quantity").val() ),
			maxQuantity: parseInt( $(this).find(".item-max-quantity").val() ),
			chances: parseInt( $(this).find(".item-chances").val() )
		}
		rewardItems.push(rewardItem);
	});
	return rewardItems;
}
function getRequiredItemsFromDiv(div) {
	let requiredItems = [];
	div.find(".required-item").each(function() {
		let requiredItem = {
			type: $(this).find(".item-type").val(),
			name: $(this).find(".item-name").val(),
			minQuantity: parseInt( $(this).find(".item-quantity").val() ),
			hasToRemove: $(this).find(".has-to-remove-checkbox").prop("checked")
		}
		requiredItems.push(requiredItem);
	});
	return requiredItems;
}
function setupPickupObject(workflowItem) {
	const data = workflowItem.data || {};
	const div = $(`
	
		${getLocalizedText("menu:setup")} 
		
	 
	`);
	div.find(".highlight-when-near").prop("checked", data.highlightWhenNear);
	const divForStaticIdInput = createDivForStaticIdInput("object", data.staticId);
	// Add the div as first element of .setup-div
	div.find(".setup-div").prepend(divForStaticIdInput);
	const requiredItemsDiv = createDivForRequiredItemsList(data.requiredItems);
	div.append(requiredItemsDiv);
	const rewardItemsDiv = createDivForRewardItemsList(data.rewardItems, data.rewardMinAmount, data.rewardMaxAmount);
	div.append(rewardItemsDiv);
	const animationsBtn = div.find(".animations-btn");
	animationsBtn.click(async function() {
		const oldAnimations = animationsBtn.data("animationsData");
	
		const animations = await animationsDialog(oldAnimations);
		if (!animations) return;
	
		animationsBtn.data("animationsData", animations);
	}).data("animationsData", data.animationsData || getDefaultAnimationsData());
	const customizeBlipBtn = div.find(".customize-blip-btn");
	customizeBlipBtn.click(async function() {
		const oldBlipData = customizeBlipBtn.data("blipData");
		const blipData = await blipDialog(oldBlipData);
		if (!blipData) return;
		customizeBlipBtn.data("blipData", blipData);
	}).data("blipData", data.blipData || getDefaultBlipCustomization());
	const customizeMarkerBtn = div.find(".customize-marker-btn");
	customizeMarkerBtn.click(async function() {
		const oldMarkerData = customizeMarkerBtn.data("markerData");
		const markerData = await markerDialog(oldMarkerData);
		if (!markerData) return;
		customizeMarkerBtn.data("markerData", markerData);
	}).data("markerData", data.markerData || getDefaultMarkerCustomization());
	
	return div;
}
function setupBlowupEntity(workflowItem) {
	const data = workflowItem.data || {};
	const div = $(`
	
		${getLocalizedText("menu:setup")} 
		
		
		
		
	 
	`);
	const divForStaticIdInput = createDivForStaticIdInput("object", data.staticId);
	// Add the div as first element of .setup-div
	div.find(".setup-div").prepend(divForStaticIdInput);
	return div;
}
function setupKillPed(workflowItem) {
	const data = workflowItem.data || {};
	const div = $(`
	
		${getLocalizedText("menu:setup")} 
		
		
		
		
	 
	`);
	const divForStaticIdInput = createDivForStaticIdInput("ped", data.staticId);
	// Add the div as first element of .setup-div
	div.find(".setup-div").prepend(divForStaticIdInput);
	return div;
}
function setupProtectPed(workflowItem) {
	const data = workflowItem.data || {};
	const div = $(`
	
		${getLocalizedText("menu:setup")} 
		
		
		${getLocalizedText("menu:attackers")} 
	 
	`);
	const difficultyDiv = createDivForDifficulty(true, data.toughness);
	div.find(".setup-div").append(difficultyDiv);
	const divForStaticIdInput = createDivForStaticIdInput("ped", data.staticId);
	// Add the div as first element of .setup-div
	div.find(".setup-div").prepend(divForStaticIdInput);
	const divForAttackersList = createDivForStaticIdsList("ped", data.attackersStaticIds);
	div.append(divForAttackersList);
	return div;
}
function setupPlayMinigame(workflowItem) {
	const data = workflowItem.data || {};
	const div = $(`
	
		${getLocalizedText("menu:setup")} 
		
		${getLocalizedText("menu:coordinates")} 
	 
	`);
	const divForCoordinatesWithRadius = createDivForCoordinates(data);
	div.append(divForCoordinatesWithRadius);
	div.find(".choose-minigame-btn").click(async function() {
		const ALL_MINIGAMES_NAMES = await $.post(`https://${resName}/getAllMinigames`);
		
		const elements = ALL_MINIGAMES_NAMES.map(function(minigame) {
			return {label: firstCharToUpperCase(minigame), value: minigame};
		});
		const minigameName = await listDialog(getLocalizedText("menu:choose"), getLocalizedText("menu:search"), elements);
		if(!minigameName) return;
		div.find(".minigame-name").val(minigameName);
	}).tooltip();
	const requiredItemsDiv = createDivForRequiredItemsList(data.requiredItems);
	div.append(requiredItemsDiv);
	const rewardItemsDiv = createDivForRewardItemsList(data.rewardItems, data.rewardMinAmount, data.rewardMaxAmount);
	div.append(rewardItemsDiv);
	return div;
}
function setupLeaveArea(workflowItem) {
	const data = workflowItem.data || {};
	const div = $(`
	
		
${getLocalizedText("menu:setup")} 
	
	`);
	const divForCoordinatesWithRadius = createDivForCoordinates(data);
	div.find('.setup-title').after(divForCoordinatesWithRadius);
	return div;
}
function setDialoguePieceAudioFile(div, audioFile) {
	if(audioFile) {
		div.find(".choose-audio-btn").data("audioFile", audioFile);
		div.find(".choose-audio-btn").text(audioFile);
	} else {
		div.find(".choose-audio-btn").data("audioFile", undefined);
		div.find(".choose-audio-btn").text(getLocalizedText("menu:choose_audio"));
	}
}
function addDialoguePieceInList(listDiv, dialoguePiece={}) {
	const div = $(`
	
	`);
	div.find(".choose-audio-btn").click(async function() {
		const ALL_AUDIO_FILES = await $.post(`https://${resName}/getAllAudioFiles`);
		const elements = ALL_AUDIO_FILES.map(audioFile => { return {label: audioFile, value: audioFile} });
		const audioFile = await listDialog(getLocalizedText("menu:choose"), getLocalizedText("menu:search"), elements, getLocalizedText("menu:no_audio_files_found"));
		setDialoguePieceAudioFile(div, audioFile);
	});
	setDialoguePieceAudioFile(div, dialoguePiece.audioFile);		
	div.find(".btn-close").click(function() {
		div.remove();
	});
	listDiv.append(div);
}
function createDivForDialogueList(dialogue=[]) {
	const div = $(`
		
			Dialogue 
			
			${getLocalizedText("menu:no_elements_added")}
			
				${getLocalizedText("menu:add_message")} 
			
	`);
	div.find(".add-dialogue-piece-btn").click(function() {
		addDialoguePieceInList(div.find(".dialogue-setup-list"));
	});
	dialogue.forEach(function(dialoguePiece) {
		addDialoguePieceInList(div.find(".dialogue-setup-list"), dialoguePiece);
	});
	if(dialogue.length == 0) {
		addDialoguePieceInList(div.find(".dialogue-setup-list"));
	}
	return div;
}
function getDialogueFromDiv(div) {
	let dialogue = [];
	div.find(".dialogue-piece").each(function() {
		let dialoguePiece = {
			title: $(this).find(".dialogue-piece-title").val(),
			message: $(this).find(".dialogue-piece-message").val(),
			secondsDuration: parseInt( $(this).find(".seconds-duration").val() ),
			audioFile: $(this).find(".choose-audio-btn").data("audioFile")
		}
		dialogue.push(dialoguePiece);
	});
	return dialogue;
}
function setupTalkToPed(workflowItem) {
	const data = workflowItem.data || {};
	const div = $(`
	
		${getLocalizedText("menu:setup")} 
		
		
	 
	`);
	const divForStaticIdInput = createDivForStaticIdInput("ped", data.staticId);
	// Add the div as first element of .setup-div
	div.find(".setup-div").prepend(divForStaticIdInput);
	const dialogueDiv = createDivForDialogueList(data.dialogue);
	div.append(dialogueDiv);
	
	const requiredItemsDiv = createDivForRequiredItemsList(data.requiredItems);
	div.append(requiredItemsDiv);
	const rewardItemsDiv = createDivForRewardItemsList(data.rewardItems, data.rewardMinAmount, data.rewardMaxAmount);
	div.append(rewardItemsDiv);
	return div;
}
function setupPlayAnimation(workflowItem) {
	const data = workflowItem.data || {};
	const div = $(`
	
		${getLocalizedText("menu:setup")} 
		
			${getLocalizedText("menu:choose_animations")} 
		
		${getLocalizedText("menu:coordinates")} 
	 
	`);
	const animationsBtn = div.find(".animations-btn");
	animationsBtn.click(async function() {
		const oldAnimations = animationsBtn.data("animationsData");
		const animations = await animationsDialog(oldAnimations);
		if (!animations) return;
		animationsBtn.data("animationsData", animations);
	}).data("animationsData", data.animationsData || getDefaultAnimationsData());
	const divForCoordinatesWithRadius = createDivForCoordinates(data);
	div.append(divForCoordinatesWithRadius);
	const requiredItemsDiv = createDivForRequiredItemsList(data.requiredItems);
	div.append(requiredItemsDiv);
	const rewardItemsDiv = createDivForRewardItemsList(data.rewardItems, data.rewardMinAmount, data.rewardMaxAmount);
	div.append(rewardItemsDiv);
	return div;
}
function addElementInListedElements(listDiv, element) {
	const div = $(`
	
		${element} 
		
			 
	 
	`);
	div.find(".btn-close").click(function() {
		div.remove();
	});
	listDiv.append(div);
}
function createDivForListedElements(id, title, placeholder, buttonText, elements=[]) {
	const div = $(`
	
	`);
	div.find(".add-element-btn").click(function() {
		const elementInputDiv = div.find(".element-id");
		const elementId = elementInputDiv.val();
		if(!elementId || elementId == "") return;
		elementInputDiv.val("");
		addElementInListedElements(div.find(`.${id}`), elementId);
	});
	elements.forEach(function(elementId) {
		addElementInListedElements(div.find(`.${id}`), elementId);
	});
	return div;
}
function getListedElementsFromDiv(div) {
	let elements = [];
	div.find(".element").each(function() {
		elements.push($(this).text());
	});
	return elements;
}
function createDivForDifficulty(isReverse = false, difficulty = 2) {
	const RADIO_NAME = generateStaticId(); // So radio name will be random and won't bother
	const div = $(`
	
		${getLocalizedText("menu:easy")} 
		${getLocalizedText("menu:normal")} 
		${getLocalizedText("menu:hard")} 
	
	`);
	// Add values to inputs
	div.find("input").each(function(index, element) {
		const totalElements = div.find("input").length;
		const value = isReverse ? totalElements - index : index + 1;
		$(element).val(value);
	});
	// Set the default value
	div.find(`input[value="${difficulty}"]`).prop("checked", true);
	return div;
}
function getDifficultyFromDiv(div) {
	return parseInt( div.find(".difficulty:checked").val() );
}
function setupSurvive(workflowItem) {
	const data = workflowItem.data || {};
	const div = $(`
	
		${getLocalizedText("menu:setup")} 
		
		
		
		${getLocalizedText("menu:coordinates")} 
	 
	`);
	const difficultyDiv = createDivForDifficulty(false, data.toughness);
	div.find(".setup-div").append(difficultyDiv);
	const divForCoordinatesWithRadius = createDivForCoordinates(data, true, true, false);
	div.append(divForCoordinatesWithRadius);
	const divForPossibleModels = createDivForListedElements("ped-models", getLocalizedText("menu:possible_models"), getLocalizedText("menu:model"), getLocalizedText("menu:add_model"), data.possiblePedsModels);
	div.find(".lists").append(divForPossibleModels);
	
	const divForPossibleWeapons = createDivForListedElements("weapons", getLocalizedText("menu:possible_weapons"), getLocalizedText("menu:weapon"), getLocalizedText("menu:add_weapon"), data.possibleWeapons);
	div.find(".lists").append(divForPossibleWeapons);
	// Set old data
	div.find(".minutes-to-survive").val(data.minutesToSurvive);
	div.find(".max-enemies").val(data.maxEnemies);
	div.find(".customize-blip-btn").data("blipData", data.blipData);
	return div;
}
function setupVehicleAttack(workflowItem) {
	const data = workflowItem.data || {};
	const div = $(`
	
		${getLocalizedText("menu:setup")} 
		
		
		
	 
	`);
	const difficultyDiv = createDivForDifficulty(false, data.toughness);
	div.find(".setup-div").append(difficultyDiv);
	
	const divForPossibleModels = createDivForListedElements("ped-models", getLocalizedText("menu:possible_models"), getLocalizedText("menu:model"), getLocalizedText("menu:add_model"), data.possiblePedsModels);
	div.find(".lists").append(divForPossibleModels);
	
	const divForPossibleWeapons = createDivForListedElements("weapons", getLocalizedText("menu:possible_weapons"), getLocalizedText("menu:weapon"), getLocalizedText("menu:add_weapon"), data.possibleWeapons);
	div.find(".lists").append(divForPossibleWeapons
	);
	const divForPossibleVehicles = createDivForListedElements("vehicles-models", getLocalizedText("menu:possible_vehicles_models"), getLocalizedText("menu:vehicle"), getLocalizedText("menu:add_vehicle"), data.possibleVehiclesModels);
	div.find(".lists").append(divForPossibleVehicles);
	return div;
}
function setupWaitInCoordinates(workflowItem) {
	const data = workflowItem.data || {};
	const div = $(`
	
		${getLocalizedText("menu:setup")} 
		
	 
	`);
	const divForCoordinatesWithRadius = createDivForCoordinates(data);
	div.find(".setup-div").append(divForCoordinatesWithRadius);
	return div;
}
async function createWorkflowItem(stageUniqueId, workflowItem, workflowType) {
	const workflowItemIndex = workflowItem.index || getWorkflowItemIndexForThisStage();
	const label = workflowItem.label || getLocalizedText(workflowItem.type);
	let parent = $(`
	
		
		
			${getLocalizedText("menu:generic")} 
			
		 
	 
	`);
	let child = null;
	if(workflowType != "tasks") {
		parent.find(".generic-div").remove();
	}
	parent.find(".is-optional").prop("checked", workflowItem.isOptional);
	parent.find(".requires-all-players").prop("checked", workflowItem.requiresAllPlayers);
	parent.find("[data-bs-toggle=tooltip]").tooltip();
	switch(workflowItem.type) {
		case "spawn_entity_in_coords": {
			if(!workflowItem.data?.label) { // If the user is creating it right now
				const label = await input(getLocalizedText("menu:label"), getLocalizedText("menu:entity_label"), getLocalizedText("menu:it_cannot_be_changed_after_creating_it"));
				if(!label) return;
				workflowItem.label = label;
				const type = await listDialog(getLocalizedText("menu:choose"), getLocalizedText("menu:search"), [
					{label: getLocalizedText("menu:ped"), value: "ped"},
					{label: getLocalizedText("menu:vehicle"), value: "vehicle"},
					{label: getLocalizedText("menu:object"), value: "object"},
				]);
				if(!type) return;
				workflowItem.data = {label, type};
			}
			
			child = setupSpawnEntityInCoordsDiv(workflowItem);
			break;
		}
		case "delete_entities": {
			child = setupDeleteEntitiesDiv(workflowItem);
			break;
		}
		case "trigger_client_event": {
			child = setupTriggerClientEventDiv(workflowItem);
			break;
		}
		case "trigger_event": {
			child = setupTriggerEventDiv(workflowItem);
			break;
		}
		case "give_items": {
			child = setupGiveItemsDiv(workflowItem);
			break;
		}
		case "alert_police": {
			child = setupAlertPoliceDiv(workflowItem);
			break;
		}
		case "message": {
			child = setupMessageDiv(workflowItem);
			break;
		}
		case "walk_ped_to_coords": {
			child = setupWalkPedToCoordsDiv(workflowItem);
			break;
		}
		case "wander_ped": {
			child = setupWanderPedDiv(workflowItem);
			break;
		}
		case "set_doorlock": {
			child = setupSetDoorlockDiv(workflowItem);
			break;
		}
		case "teleport_players": {
			child = setupTeleportPlayersDiv(workflowItem);
			break;
		}
		case "goto_coordinates": {
			child = setupGoToCoordinates(workflowItem);
			break;
		}
		case "enter_vehicle": {
			child = setupEnterVehicle(workflowItem);
			break;
		}
		case "deliver_vehicle": {
			child = setupDeliverVehicle(workflowItem);
			break;
		}
		case "pickup_object": {
			child = setupPickupObject(workflowItem);
			break;
		}
		case "blowup_entity": {
			child = setupBlowupEntity(workflowItem);
			break;
		}
		case "kill_ped": {
			child = setupKillPed(workflowItem);
			break;
		}
		case "protect_ped": {
			child = setupProtectPed(workflowItem);
			break;
		}
		case "play_minigame": {
			child = setupPlayMinigame(workflowItem);
			break;
		}
		case "leave_area": {
			child = setupLeaveArea(workflowItem);
			break;
		}
		case "talk_to_ped": {
			child = setupTalkToPed(workflowItem);
			break;
		}
		case "play_animation": {
			child = setupPlayAnimation(workflowItem);
			break;
		}
		case "survive": {
			child = setupSurvive(workflowItem);
			break;
		}
		case "vehicle_attack": {
			child = setupVehicleAttack(workflowItem);
			break;
		}
		case "wait_in_coordinates": {
			child = setupWaitInCoordinates(workflowItem);
			break;
		}
	}
	parent.append(child);
	$("#stage-elements-container").append(parent);
}
function loadWorkflowItems(stageData) {
	if(stageData.startingActions) {
		stageData.startingActions.forEach(async function(workflowItem) {
			await createWorkflowItem(stageData.uniqueId, workflowItem, "startingActions");
		});
	}
	if(stageData.endingActions) {
		stageData.endingActions.forEach(async function(workflowItem) {
			await createWorkflowItem(stageData.uniqueId, workflowItem, "endingActions");
		});
	}
	if(stageData.tasks) {
		stageData.tasks.forEach(async function(workflowItem) {
			await createWorkflowItem(stageData.uniqueId, workflowItem, "tasks");
		});
	}
}
function deleteStageUniqueId(stageUniqueId) {
	$(`.stage-options[data-stage-unique-id=${stageUniqueId}]`).remove();
	$(`.workflow-item[data-stage-unique-id=${stageUniqueId}]`).remove();
	$("#stages-list").find(`.list-group-item[data-stage-unique-id=${stageUniqueId}]`).remove();
}
function createStage(stageData={}) {
	const stageUniqueId = stageData.uniqueId || generateStaticId();
	
	const stageLabel = stageData.label || getLocalizedText("menu:new_stage");
	const stageListElementDiv = $(`		
	
		${stageLabel} 
		
			 
	 
	`);
	stageListElementDiv.find(".btn-close").click(async function() {
		const wantsToDelete = await confirmDeletion(getLocalizedText("menu:delete_stage:warning"));
		if(!wantsToDelete) return;
		deleteStageUniqueId(stageUniqueId);
	});
	stageListElementDiv.insertBefore(".create-new-stage");
	const stageOptionsDiv = $(`
	
	`);
	stageOptionsDiv.find(".stage-label").keyup(function() {
		const label = $(this).val() || "!!!!!!!!!";
		stageListElementDiv.find(".stage-label-in-list").text(label);
	});
	loadWorkflowItems(stageData);
	$("#mission-header-div").append(stageOptionsDiv);
}
$("#stages-list").click(function(event) {
	const target = $(event.target).closest(".list-group-item-action"); // So it works also if the click is on the span inside the li
	if(target.hasClass("create-new-stage")) { createStage(); return; }
	// If it's not the button, it's an existing stage
	const stageUniqueId = target.data("stageUniqueId");
	toggleStage(stageUniqueId);	
})
function changeStageUniqueId(oldIndex, newIndex) {
	let elementsWithOldIndex = {}; 
	const elements = $(`.[data-stage-unique-id]`);
	
	elements.forEach(function(element) {
		const stageUniqueId = $(element).data("stageUniqueId");
		
		if(!elementsWithOldIndex[stageUniqueId]) {
			elementsWithOldIndex[stageUniqueId] = [];
		}
		elementsWithOldIndex[stageUniqueId].push(element);
	});
	const elementsToChange = elementsWithOldIndex[oldIndex];
}
function loadStages(stages) {
	const stagesListDiv = $("#stages-list");
	// Reset
	stagesListDiv.html(`
${getLocalizedText("menu:create_new_stage")} `);
	resetWorkflowTypesSelection();
	$("#stage-workflow-items-selection-list").html(`
${getLocalizedText("menu:select_something")} `);
	$("#stage-elements-container").html("");
	$("#stages-list").sortable({
		cancel: ".create-new-stage",
		beforeStop: function( event, ui ) {
			if (!ui.item.prev().hasClass("create-new-stage")) return;
			$("#stages-list").sortable("cancel");
		},
		update: async function(event, ui) {
			const wantsToMove= await confirmDeletion(getLocalizedText("menu:move_stage:warning"));
			if(!wantsToMove) {
				$("#stages-list").sortable("cancel");
				return;
			}
		}
	});
	// Cleanup stage options (label, time, description)
	$("#mission-header-div .stage-options").remove();
	for(let stageIndex=0; stageIndex < stages.length; stageIndex++) {
		let stageData = stages[stageIndex];
		stageData.uniqueId = generateStaticId();
		createStage(stageData);
	}
}
$("#mission-can-be-repeated").change(function() {
	const isChecked = $(this).prop("checked");
	$("#mission-cooldown-hours-div").toggle(isChecked).prop("required", isChecked);
});
function editMission(id) {
	const missionInfo = missions[id];
	const missionOptions = missionInfo.options;
	let missionModal = $("#mission-modal");
	// Converts from create modal to edit modal
	missionModal.data("action", "edit");
	missionModal.data("missionId", id);
	$("#delete-mission-btn").show();
	$("#save-mission-btn").text( getLocalizedText("menu:save") );
	
	// Options
	$("#mission-label").val(missionInfo.label);
	$("#mission-description").val(missionInfo.description);
	$("#mission-minimum-players").val(missionOptions.minPlayers);
	$("#mission-maximum-players").val(missionOptions.maxPlayers);
	$("#mission-can-be-repeated").prop("checked", missionOptions.canBeRepeated).change();
	$("#mission-cooldown-hours").val(missionOptions.cooldownHours);
	$("#mission-minutes-before-cleanup").val(missionOptions.minutesBeforeCleanup);
	$("#mission-allow-multiple-sessions").prop("checked", missionOptions.allowMultipleSessions);
	// Requirements
	setRequiredMissions(missionOptions.requiredMissions);
	setAllowedJobs(missionOptions.allowedJobs);
	$("#mission-minimum-police").val(missionOptions.minimumPolice || 0);
	// Mission start
	$("#mission-start-coordinates-x").val(missionOptions.startCoordinates?.x);
	$("#mission-start-coordinates-y").val(missionOptions.startCoordinates?.y);
	$("#mission-start-coordinates-z").val(missionOptions.startCoordinates?.z);
	$("#mission-start-customize-blip-btn").data("blipData", missionOptions.blipData);
	$("#mission-start-customize-marker-btn").data("markerData", missionOptions.markerData);
	$("#mission-start-customize-ped-btn").data("pedData", missionOptions.pedData);
	// Stages
	loadStages(missionInfo.stages);
	missionModal.modal("show");
}
function setDefaultDataOfMission() {
	// Options
	$("#mission-label").val("");
	$("#mission-description").val("");
	$("#mission-minimum-players").val(1);
	$("#mission-maximum-players").val(4);
	$("#mission-can-be-repeated").prop("checked", true).change();
	$("#mission-cooldown-hours").val(0);
	$("#mission-minutes-before-cleanup").val(5);
	$("#mission-allow-multiple-sessions").prop("checked", true);
	
	// Requirements
	setRequiredMissions([]);
	setAllowedJobs(false);
	$("#mission-minimum-police").val(0);
	// Mission start
	$("#mission-start-coordinates-x").val("");
	$("#mission-start-coordinates-y").val("");
	$("#mission-start-coordinates-z").val("");
	$("#mission-start-customize-blip-btn").data("blipData", getDefaultBlipCustomization() );
	$("#mission-start-customize-marker-btn").data("markerData", getDefaultMarkerCustomization() );
	$("#mission-start-customize-ped-btn").data("pedData", getDefaultPedCustomization() );
	loadStages([]);
	toggleStage(null);
}
$("#new-mission-btn").click(function() {
	let missionModal = $("#mission-modal");
	// Converts from edit modal to create modal
	missionModal.data("action", "create");
	
	$("#delete-mission-btn").hide();
	$("#save-mission-btn").text( getLocalizedText("menu:create") );
	
	setDefaultDataOfMission();
	missionModal.modal("show");
})
function getStages() {
	let stages = [];
	$(".stage-list-item").each(function(index, element) {
		const stageUniqueId = $(element).data("stageUniqueId");
		const stageOptionsDiv = $(`#mission-header-div [data-stage-unique-id='${stageUniqueId}']`);
		const stageData = {
			label: $(stageOptionsDiv).find(".stage-label").val(),
			maxMinutesDuration: parseInt( $(stageOptionsDiv).find(".stage-max-minutes-duration").val() ),
			description: $(stageOptionsDiv).find(".stage-description").val(),
			startingActions: getWorkflowItemsDataForStage(stageUniqueId, "startingActions"),
			endingActions: getWorkflowItemsDataForStage(stageUniqueId, "endingActions"),
			tasks: getWorkflowItemsDataForStage(stageUniqueId, "tasks"),
		}
		stages.push(stageData);
	});
	return stages;
}
function clearHelperErrorsInForm(form) {
	form.find(".legend-circle").remove();
}
function showErrorsInForm(form) {
	clearHelperErrorsInForm(form);
	form.find(":invalid").each(function(index, element) {
		// Verify if the issue is on stage options (label, description, max duration)
		const stageUniqueId = $(element).closest(".stage-options").data("stageUniqueId") || $(element).closest(".workflow-item").data("stageUniqueId");
		if(!stageUniqueId) return;
		
		const stageElement = $(`#stages-list [data-stage-unique-id='${stageUniqueId}']`);
		// Check if the stage has a legend-circle
		if(stageElement.find(".legend-circle").length == 0) {
			stageElement.prepend(`
`);
		}
		const workflowType = $(element).closest(".workflow-item").data("workflowType");
		// Check if the workflow type has a legend-circle
		if(!workflowType) return;
		const workflowTypeElement = $(`#stage-workflow-types-selection-list [data-workflow-type='${workflowType}']`);
		if(workflowTypeElement.find(".legend-circle").length == 0) {
			workflowTypeElement.prepend(`
`);
		}
		// Check if the workflow item has a legend-circle
		const workflowItemIndex = $(element).closest(".workflow-item").data("workflowItemIndex");
		const workflowItemElement = $(`#stage-workflow-items-selection-list [data-workflow-item-index='${workflowItemIndex}']`);
		if(workflowItemElement.find(".legend-circle").length > 0) return;
		workflowItemElement.prepend(`
`);
	})
}
$("#mission-form").submit(async function(event) {
	if(isThereAnyErrorInForm(event)) {
		showErrorsInForm($(this));
		return;
	};
	let missionModal = $("#mission-modal");
	let action = missionModal.data("action");
	let missionInfo = {
		label: $("#mission-label").val(),
		description: $("#mission-description").val(),
		
		options: {
			minPlayers: parseInt( $("#mission-minimum-players").val() ),
			maxPlayers: parseInt( $("#mission-maximum-players").val() ),
			canBeRepeated: $("#mission-can-be-repeated").prop("checked"),
			cooldownHours: parseInt( $("#mission-cooldown-hours").val() ),
			minutesBeforeCleanup: $("#mission-minutes-before-cleanup").val(),
			allowMultipleSessions: $("#mission-allow-multiple-sessions").prop("checked"),
			startCoordinates: {
				x: parseFloat( $("#mission-start-coordinates-x").val() ),
				y: parseFloat( $("#mission-start-coordinates-y").val() ),
				z: parseFloat( $("#mission-start-coordinates-z").val() ),
			},
			blipData: $("#mission-start-customize-blip-btn").data("blipData"),
			markerData: $("#mission-start-customize-marker-btn").data("markerData"),
			pedData: $("#mission-start-customize-ped-btn").data("pedData"),
			// Requirements
			requiredMissions: $("#mission-required-missions").data("requiredMissions"),
			allowedJobs: $("#mission-allowed-jobs").data("allowedJobs"),
			minimumPolice: parseInt( $("#mission-minimum-police").val() )
		},
		stages: getStages()
	}
	
	let success = null;
	switch(action) {
		case "create": {
			success = await $.post(`https://${resName}/createMission`, JSON.stringify(missionInfo));
			break;
		}
		case "edit": {
			success = await $.post(`https://${resName}/updateMission`, JSON.stringify({missionId: missionModal.data("missionId"), missionInfo: missionInfo}));
			break;
		}
	}
	if(!success) return;
	missionModal.modal("hide");
	loadMissions();
})
$("#delete-mission-btn").click(async function() {
	if(!await confirmDeletion()) return;
	let missionModal = $("#mission-modal");
	let missionId = missionModal.data("missionId");
	const success = await $.post(`https://${resName}/deleteMission`, JSON.stringify({missionId: missionId}));
	if(!success) return;
	missionModal.modal("hide");
	loadMissions();
});
$("#mission-start-choose-coords-btn").click(async function() {
	const data = await chooseCoords();
	if(!data) return;
	$("#mission-start-coordinates-x").val(data.coords.x);
	$("#mission-start-coordinates-y").val(data.coords.y);
	$("#mission-start-coordinates-z").val(data.coords.z);
});
$("#mission-start-customize-blip-btn").click(async function() {
	const oldBlipData = $(this).data("blipData");
	const blipData = await blipDialog(oldBlipData);
	if(!blipData) return;
	$(this).data("blipData", blipData);
});
$("#mission-start-customize-marker-btn").click(async function() {
	const oldMarkerData = $(this).data("markerData");
	const markerData = await markerDialog(oldMarkerData);
	if(!markerData) return;
	$(this).data("markerData", markerData);
});
$("#mission-start-customize-ped-btn").click(async function() {
	const oldPedData = $(this).data("pedData");
	const pedData = await pedDialog(oldPedData);
	if(!pedData) return;
	$(this).data("pedData", pedData);
});
function setRequiredMissions(requiredMissions=[]) {
	$("#mission-required-missions").val(requiredMissions.join(", ")).data("requiredMissions", requiredMissions);
	if(requiredMissions.length == 0) {
		$("#mission-required-missions").val(getLocalizedText("menu:none"));
	}
}
$("#mission-required-missions-choose-btn").click(async function() {
	const oldRequiredMissions = $("#mission-required-missions").data("requiredMissions") || [];
	const elements = Object.values(missions).map(function(mission) {
		return {label: mission.label, value: mission.id};
	});
	const requiredMissionsIds = await listArrayDialog(
		getLocalizedText("menu:choose"),
		getLocalizedText("menu:search"),
		elements,
		oldRequiredMissions,
		"N\\A"
		);
	if(!requiredMissionsIds) return;
	setRequiredMissions(requiredMissionsIds);
});
function setAllowedJobs(allowedJobs = false) {
	$("#mission-allowed-jobs").data("allowedJobs", allowedJobs);
	$("#mission-allowed-jobs").tooltip("dispose");
	if(allowedJobs === false) {
		$("#mission-allowed-jobs").val(getLocalizedText("menu:all_jobs_allowed"));
		return;
	}
	const jobsLabel = Object.keys(allowedJobs).join(", ");
	
	$("#mission-allowed-jobs").val(jobsLabel);
	// Add tooltip 
	$("#mission-allowed-jobs").attr("title", jobsLabel);
	$("#mission-allowed-jobs").tooltip();
}
$("#mission-allowed-jobs-choose-btn").click(async function() {
	const oldAllowedJobs = $("#mission-allowed-jobs").data("allowedJobs");
	const newAllowedJobs = await jobsDialog(oldAllowedJobs);
	setAllowedJobs(newAllowedJobs);
});
// [[ NEXUS ]]
const voteInstanceRater = raterJs({
	starSize: 35,
	element: document.querySelector("#vote-instance-rater"),
	rateCallback: async function rateCallback(rating, done) {
		const instanceId = $("#nexus-modal").data("instance").id;
		const success = await $.post(`https://${resName}/nexus/rateInstance`, JSON.stringify({rating, instanceId}));
		if(success) voteInstanceRater.setRating(rating);
		done();
	}
});
const averageInstanceVotes = raterJs({
	starSize: 20,
	readOnly: true,
	element: document.querySelector("#nexus-modal-instance-average-rating"),
});
$("#nexus-import-instance-btn").click(async function() {
	const instance = $("#nexus-modal").data("instance");
	const id = instance.id;
	const mappedObjectsNames = await objectsMapperDialog(instance.requiredItemsNames);
	if(!mappedObjectsNames) return;
	const response = await $.post(`https://${resName}/nexus/importInstance`, JSON.stringify({id, mappedObjectsNames}));
	$("#nexus-modal").modal("hide");
	if(response === true) reloadAllData();
	showServerResponse(response);
});
let nexusDataTable = $("#nexus-table").DataTable({
	"lengthMenu": [5, 10, 15],
	"pageLength": 15,
	"order": [[7, 'desc'], [4, 'desc'], [5, 'desc']], 
	"createdRow": function (row, data, index) {
		$('td', row).css('white-space', 'nowrap').addClass("py-3");
		$(row).addClass("clickable");
		$(row).click(function () {
			const instance = $(this).data("instance");
			showInstance(instance);
			$("#nexus-modal").modal("show");
		});
	},
	"columnDefs": [{ "defaultContent": "???", "targets": "_all" }]
});
  
function showInstance(instance) {
	$("#nexus-modal").data("instance", instance);
	$("#nexus-modal-instance-listing-label").text(instance.label);
	$("#nexus-instance-content-type").text(instance.type);
	$("#nexus-modal-instance-description").text(instance.description || getLocalizedText("menu:nexus:no_description"));
	$("#nexus-modal-instance-author").text(instance.rawAuthor);
	$("#nexus-instance-stages-amount").text(instance.minifiedContent.stages.length);
	// Votes
	if(instance?.votes?.total > 0) {
		averageInstanceVotes.setRating(instance?.votes.averageRating);
	} else {
		averageInstanceVotes.setRating(0);
	}
	$("#nexus-modal-instance-total-votes").text(instance.votes?.total || 0);
	$("#nexus-modal-instance-content").html(""); // Clear content
	for(let i=0; i
			${stageData.label.toUpperCase()}${stageDescription} 
			
		  
		`);
		// Tasks
		stageData.tasks.forEach(task => {
			const taskDescription = task.description ? ` - ${task.description}` : "";
			const taskDiv = $(`
${task.label}${taskDescription}
`);
			stageDiv.find(".nexus-tasks-list").append(taskDiv);
		});
		$("#nexus-modal-instance-content").append(stageDiv);
	}
	// This server vote
	voteInstanceRater.setRating(0);
}
$("#upload-to-nexus-btn").click(async function() {
	let dataToChooseFrom = await $.post(`https://${resName}/getAllMissions`);
	const type = "mission";
	let elements = [];
	Object.values(dataToChooseFrom).forEach(data => {
		elements.push({
			value: data.id,
			label: data.id + " - " + (data.label || data.name)
		});
	})
	
	const selectedData = await listDialog(getLocalizedText("menu:nexus:data_to_share"), getLocalizedText("menu:search"), elements, getLocalizedText("menu:no_missions_created"))
	if(!selectedData) return;
	$("#nexus-modal-upload").data("selectedData", selectedData);
	$("#nexus-modal-upload").data("dataType", type);
	$("#nexus-upload-label").val("");
	$("#nexus-upload-description").val("");
	$("#nexus-upload-accept-tos").prop("checked", false);
	
	$("#nexus-modal-upload").modal("show");
});
$("#nexus-upload-form").submit(async function(event) {
	if(isThereAnyErrorInForm(event)) return;
	const dataToUpload = {
		type: $("#nexus-modal-upload").data("dataType"),
		id: $("#nexus-modal-upload").data("selectedData"),
		label: $("#nexus-upload-label").val(),
		description: $("#nexus-upload-description").val(),
	}
	const result = await $.post(`https://${resName}/nexus/uploadData`, 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 sharedData = await $.get(`https://${resName}/nexus/getSharedData`);
	if(!sharedData) {
		swal("Error", getLocalizedText("menu:nexus:not_available"), "error");
		resetNexus();
		return;
	} 
	
	nexusDataTable.clear()
	Object.values(sharedData).forEach(instance => {
		const roundedAverageRating = instance?.votes?.averageRating ? Math.round(instance.votes.averageRating) : 0;
		const ratingStars = instance?.votes?.total ? "⭐".repeat(roundedAverageRating) : getLocalizedText("menu:nexus:not_rated");
		const limitedDescription = instance.description?.length > 50 ? instance.description.substring(0, 50) + "..." : instance.description;
		const stagesCount = instance.minifiedContent.stages.length;
		const rawRow = nexusDataTable.row.add( [instance.label, limitedDescription, stagesCount, ratingStars, instance.votes?.total || 0, instance.downloadCount, instance.author, (instance.featured ? "💡" : "⚪")] );
		const rowDiv = $(rawRow.node());
		$(rowDiv).data("instance", instance);
	})
	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();
}
/*
███████ ████████  █████  ████████ ███████ 
██         ██    ██   ██    ██    ██      
███████    ██    ███████    ██    ███████ 
     ██    ██    ██   ██    ██         ██ 
███████    ██    ██   ██    ██    ███████ 
*/
let currentPage = 0;
const itemsPerPage = 10;
const MissionsStatisticsChart = new Chart(document.getElementById('missions-statistics-canvas').getContext('2d'), {
	type: 'bar',
	data: {
		labels: "Missions",
		datasets: []
	},
	options: {
		scales: {
			y: {
				beginAtZero: true
			}
		},
		devicePixelRatio: 2,
	}
});
function loadAllMissionsLikesDislikes(statistics) {
    const labels = statistics.map(stat => `${missions[stat.template_id].label}`);
    const likesData = statistics.map(stat => stat.likes);
    const dislikesData = statistics.map(stat => stat.dislikes);
    MissionsStatisticsChart.data = {
        labels: labels,
        datasets: [{
            label: 'Likes',
            data: likesData,
            backgroundColor: 'rgba(46, 204, 113,0.5)',
            borderColor: 'rgba(46, 204, 113,1.0)',
            borderWidth: 1
        }, {
            label: 'Dislikes',
            data: dislikesData,
            backgroundColor: 'rgba(192, 57, 43,0.5)',
            borderColor: 'rgba(192, 57, 43,1.0)',
            borderWidth: 1
        }]
    };
    MissionsStatisticsChart.update();
}
function loadAllMissionsSuccessFailure(statistics) {
    const labels = statistics.map(stat => `${missions[stat.template_id].label}`);
    const successData = statistics.map(stat => stat.success_count);
    const failureData = statistics.map(stat => stat.fail_count);
    MissionsStatisticsChart.data = {
        labels: labels,
        datasets: [{
            label: 'Success',
            data: successData,
            backgroundColor: 'rgba(46, 204, 113,0.5)',
            borderColor: 'rgba(46, 204, 113,1.0)',
            borderWidth: 1
        }, {
            label: 'Failure',
            data: failureData,
            backgroundColor: 'rgba(192, 57, 43,0.5)',
            borderColor: 'rgba(192, 57, 43,1.0)',
            borderWidth: 1
        }]
    };
    MissionsStatisticsChart.update();
}
function getPaginatedData(statistics, page) {
    const start = page * itemsPerPage;
    const end = start + itemsPerPage;
    return statistics.slice(start, end);
}
function loadPaginatedData(statistics, action) {
    const paginatedStatistics = getPaginatedData(statistics, currentPage);
    if (action === "likes-dislikes") {
        loadAllMissionsLikesDislikes(paginatedStatistics);
    } else if (action === "success-failure") {
        loadAllMissionsSuccessFailure(paginatedStatistics);
    }
}
function nextPage(statistics, action) {
    const totalPages = Math.ceil(statistics.length / itemsPerPage);
    if (currentPage >= totalPages - 1) return;
	
	currentPage++;
	loadPaginatedData(statistics, action);
}
function prevPage(statistics, action) {
    if (currentPage <= 0) return;
	currentPage--;
	loadPaginatedData(statistics, action);
}
$("#statistics-prev-page-btn").click(async function() {
	const statistics = await $.post(`https://${resName}/getAllMissionsStatistics`);
	let action = $('input[type=radio][name=missions-statistics-type]:checked').val();
	prevPage(statistics, action);
});
$("#statistics-next-page-btn").click(async function() {
	const statistics = await $.post(`https://${resName}/getAllMissionsStatistics`);
	let action = $('input[type=radio][name=missions-statistics-type]:checked').val();
	
	nextPage(statistics, action);
});
$('input[type=radio][name=missions-statistics-type]').change(async function() {
	const statistics = await $.post(`https://${resName}/getAllMissionsStatistics`);
    let action = $(this).val();
	currentPage = 0;
	loadPaginatedData(statistics, action);
});
/*
████████ ██████   █████   ██████ ██   ██ ███████ ██████  
   ██    ██   ██ ██   ██ ██      ██  ██  ██      ██   ██ 
   ██    ██████  ███████ ██      █████   █████   ██████  
   ██    ██   ██ ██   ██ ██      ██  ██  ██      ██   ██ 
   ██    ██   ██ ██   ██  ██████ ██   ██ ███████ ██   ██ 
*/
function getTrackerDivSteps(instanceData) {
	const MAX_STAGES = instanceData.stages.length;
	const currentStageUniqueId = instanceData.currentStageUniqueId;
	const div = $(`
	
	`);
	const baseStep = $(`
	
		 
	`)
	for(let i=1; i <= MAX_STAGES; i++) {
		let currentDiv = baseStep.clone();
		currentDiv.find("button").text(i);	
		if(i < currentStageUniqueId) {
			currentDiv.addClass("visited");
		}
		if(i == currentStageUniqueId) {
			currentDiv.find(".nav-link").addClass("active");
		}
		div.append(currentDiv);
	}
	return div;
}
async function refreshMissionTracker() {
	const activeInstances = await $.post(`https://${resName}/getActiveInstances`);
	$("#missions-tracker-instances-div").empty();
	for(const instanceData of Object.values(activeInstances)) {
		const missionId = instanceData.missionId;
		const missionLabel = missions[missionId].label;
		const div = $(`
		
			${missionLabel} - ${getLocalizedText("menu:instance")} ${instanceData.instanceId} 
			
				
		 
		`);
		const stepsDiv = getTrackerDivSteps(instanceData);
		div.find(".secondary-div").prepend(stepsDiv);
		div.append("
");
		div.find("[data-bs-toggle=tooltip]").tooltip();
		
		div.find(".abort-mission-btn").click(async function() {
			const wantsToAbort = await confirmDeletion();
			if(!wantsToAbort) return;
			const success = await $.post(`https://${resName}/abortMission`, JSON.stringify({instanceId: instanceData.instanceId}));
			if(!success) return;
			refreshMissionTracker();
		})
		$("#missions-tracker-instances-div").append(div);
	}
}
$("#refresh-missions-tracker-btn").click(refreshMissionTracker);
/*
 █████  ██    ██ ██████  ██  ██████  
██   ██ ██    ██ ██   ██ ██ ██    ██ 
███████ ██    ██ ██   ██ ██ ██    ██ 
██   ██ ██    ██ ██   ██ ██ ██    ██ 
██   ██  ██████  ██████  ██  ██████  
*/
const soundQueue = [];
let currentSound = null;
window.addEventListener("message", function(event) {
	const data = event.data;
	
	if(data.action !== "playPedAudio") return;
	const sound = document.createElement("audio");
	sound.src = `../audio/${data.audioFile}`;
	sound.volume = 0.2;
	const playNextSound = () => {
		if (soundQueue.length > 0) {
			currentSound = soundQueue.shift();
			currentSound.play();
			currentSound.onended = playNextSound;
		} else {
			currentSound = null;
		}
	};
	if (currentSound && !currentSound.ended) {
		soundQueue.push(sound);
	} else {
		currentSound = sound;
		sound.play();
		sound.onended = playNextSound;
	}
});