--[[
RegisterSpecialization

Author:		Ifko[nator] 
Edit:		HappyLooser
Date:		21.12.2024
Version:	2.7

Changelog: 		v1.0 @02.01.2019 - initial implementation in FS 19
				---------------------------------------------------
				v2.0 @18.11.2021 - convert to FS 22
				---------------------------------------------------
				v2.5 @01.04.2022 - changed loading logic
				---------------------------------------------------
				v2.6 @21.04.2022 - fix for patch 1.4 and higher
				---------------------------------------------------
				v2.7 @21.12.2024 - edit to FS 25
]]

RegisterSpecialization = {};
RegisterSpecialization.modDir = g_currentModDirectory;
RegisterSpecialization.modName = g_currentModName;
RegisterSpecialization.isLoaded = false;

local modDesc = loadXMLFile("modDesc", RegisterSpecialization.modDir .. "modDesc.xml");

RegisterSpecialization.debugPriority = Utils.getNoNil(getXMLInt(modDesc, "modDesc.registerSpecializations#debugPriority"), 0);

local function printError(errorMessage, isWarning, isInfo)
	local prefix = "::ERROR:: ";
	
	if isWarning then
		prefix = "::WARNING:: ";
	elseif isInfo then
		prefix = "::INFO:: ";
	end;
	
	print(prefix .. "from the RegisterSpecialization.lua: " .. tostring(errorMessage));
end;

local function printDebug(debugMessage, priority, addString)
	if RegisterSpecialization.debugPriority >= priority then
		local prefix = "";
		
		if addString then
			prefix = "::DEBUG:: from the RegisterSpecialization.lua: ";
		end;
		
		print(prefix .. tostring(debugMessage));
	end;
end;

local function addSpecializations()
	if RegisterSpecialization.isLoaded then return;end;
	local specializationNumber = 0;

	while true do
		local specializationKey = string.format("modDesc.registerSpecializations.registerSpecialization(%d)", specializationNumber);

		if not hasXMLProperty(modDesc, specializationKey) then
			break;
		end;

		local specializationName = Utils.getNoNil(getXMLString(modDesc, specializationKey .. "#name"), "");
		local specializationClassName = Utils.getNoNil(getXMLString(modDesc, specializationKey .. "#className"), "");
		local specializationFilename = Utils.getNoNil(Utils.getFilename(getXMLString(modDesc, specializationKey .. "#filename"), RegisterSpecialization.modDir), ""); 
		local specializationTypeName = Utils.getNoNil(getXMLString(modDesc, specializationKey .. "#typeName"), "vehicle");
		local searchedSpecializations = string.split(Utils.getNoNil(getXMLString(modDesc, specializationKey .. "#searchedSpecializations"), ""), " ");

		local searchedSpecializationsString = "";

		local function getSearchedSpecializations(searchedSpecializations)
			for _, searchedSpecialization in pairs(searchedSpecializations) do
				if searchedSpecializationsString ~= "" then 
					searchedSpecialization = ", " .. searchedSpecialization; 
				end;

				searchedSpecializationsString = searchedSpecializationsString .. searchedSpecialization;
			end;

			return searchedSpecializationsString;
		end;

		printDebug("specializationName =  " .. specializationName .. " specializationClassName " .. specializationClassName .. " specializationFilename = " .. specializationFilename .. " specializationTypeName = " .. specializationTypeName .. " searchedSpecializations = " .. getSearchedSpecializations(searchedSpecializations), 1, true);
		
		local specName = RegisterSpecialization.modName..".".. specializationName;
		
		if specializationName ~= ""	and specializationClassName ~= "" and specializationFilename ~= "" and fileExists(specializationFilename) and searchedSpecializations ~= ""	and (specializationTypeName == "vehicle" or specializationTypeName == "placeable" or specializationTypeName == "handTool") then
			if specializationTypeName == "vehicle" then
				if g_specializationManager:getSpecializationByName(specializationName) == nil then
					g_specializationManager:addSpecialization(specializationName, specializationClassName, specializationFilename, nil);
				end;				
				for vehicleType, vehicle in pairs(g_vehicleTypeManager:getTypes()) do
					if vehicle ~= nil then
						for name in pairs(vehicle.specializationsByName) do
							for _, searchedSpecialization in pairs(searchedSpecializations) do	
								if string.lower(name) == string.lower(searchedSpecialization) then
									local specializationObject = g_specializationManager:getSpecializationObjectByName(specName);
									if specializationObject ~= nil and specializationObject.prerequisitesPresent ~= nil and specializationObject.prerequisitesPresent(vehicle.specializations) then
										if vehicle.specializationsByName[specName] == nil then
											g_vehicleTypeManager:addSpecialization(vehicleType, specName);
											printDebug("Added Specialization '" .. specName .. "' succsessfully to vehicle type '" .. vehicleType .. "'.", 1, true);
										end;
									else
										printDebug("Not added Specialization '" .. specName .. "' specializationObject or prerequisitesPresent missing or not true to vehicle type '" .. vehicleType .. "'.", 1, true);
									end;
								end;
							end;
						end;
					end;
				end;
			elseif specializationTypeName == "placeable" then
				if g_placeableSpecializationManager:getSpecializationByName(specializationName) == nil then
					g_placeableSpecializationManager:addSpecialization(specializationName, specializationClassName, specializationFilename, nil);
				end;
				for placeableType, placeable in pairs(g_placeableTypeManager:getTypes()) do
					if placeable ~= nil then
						for name in pairs(placeable.specializationsByName) do
							for _, searchedSpecialization in pairs(searchedSpecializations) do	
								if string.lower(name) == string.lower(searchedSpecialization) then									
									local specializationObject = g_placeableSpecializationManager:getSpecializationObjectByName(specName);
									if specializationObject ~= nil and specializationObject.prerequisitesPresent ~= nil and specializationObject.prerequisitesPresent(placeable.specializations) then										
										if placeable.specializationsByName[specName] == nil then
											g_placeableTypeManager:addSpecialization(placeableType, specName);
											printDebug("Added Specialization '" .. specName .. "' succsessfully to placeable type '" .. placeableType .. "'.", 1, true);
										end;										
									else
										printDebug("Not added Specialization '" .. specName .. "' specializationObject or prerequisitesPresent missing or not true to placeable type '" .. placeableType .. "'.", 1, true);
									end;
								end;
							end;
						end;
					end;
				end;
			elseif specializationTypeName == "handTool" then
				if g_handToolSpecializationManager:getSpecializationByName(specializationName) == nil then
					g_handToolSpecializationManager:addSpecialization(specializationName, specializationClassName, specializationFilename, nil);
				end;
				for handToolType, handTool in pairs(g_handToolTypeManager:getTypes()) do
					if handTool ~= nil then
						for name in pairs(handTool.specializationsByName) do
							for _, searchedSpecialization in pairs(searchedSpecializations) do	
								if string.lower(name) == string.lower(searchedSpecialization) then
									local specializationObject = g_handToolSpecializationManager:getSpecializationObjectByName(specName);
									if specializationObject ~= nil and specializationObject.prerequisitesPresent ~= nil and specializationObject.prerequisitesPresent(handTool.specializations) then	
										if handTool.specializationsByName[specName] == nil then
											g_handToolTypeManager:addSpecialization(handToolType, specName);
											printDebug("Added Specialization '" .. specName .. "' succsessfully to handTool type '" .. handToolType .. "'.", 1, true);
										end;
									else
										printDebug("Not added Specialization '" .. specName .. "' specializationObject or prerequisitesPresent missing or not true to handTool type '" .. handToolType .. "'.", 1, true);
									end;
								end;
							end;
						end;
					end;
				end;
			end;
		else
			if specializationName == nil then
				printError("Missing specialization name! Skipping this specialization now!", false, false);
			elseif specializationClassName == nil then
				printError("Missing specialization class name! Skipping specialization '" .. specName .. "' now!", false, false);
			elseif specializationFilename == nil then
				printError("Missing specialization filename! Skipping specialization '" .. specName .. "' now!", false, false);
			elseif searchedSpecializations == nil then
				printError("Missing searched specialization names! Skipping specialization '" .. specName .. "' now!", false, false);
			end;
		end;

		specializationNumber = specializationNumber + 1;
	end;
	RegisterSpecialization.isLoaded = true;
end;

TypeManager.validateTypes = Utils.prependedFunction(TypeManager.validateTypes, addSpecializations)
