--[[
AddConfig

Specialization for extended configurations and register new configurations.

Author:		Ifko[nator]
Datum:		04.03.2018

Version:	v3.3

History:	v1.0 @ 28.02.2017 - initial implementation - added possibility to change capacity via configuration
			-------------------------------------------------------------------------------------------------------------------------------------------------------------
			v2.0 @ 25.03.2017 - added possibility to change rim and axis color via configuration
			-------------------------------------------------------------------------------------------------------------------------------------------------------------
			v3.0 @ 21.07.2017 - added possibility to change fillable fill types and cutable fruit types via configuration
			-------------------------------------------------------------------------------------------------------------------------------------------------------------
			v3.1 @ 13.12.2017 - a little bit code optimation
			-------------------------------------------------------------------------------------------------------------------------------------------------------------
			v3.2 @ 31.12.2017 - increased the limit from 64 to 134.217.728 configurations, i hope thats enough now!
			-------------------------------------------------------------------------------------------------------------------------------------------------------------
			v3.3 @ 04.03.2018 - the capacity value from the fillUnit in the xml file will now set to the new capacity to avoid fill the fill volume too fast or too slow
			-------------------------------------------------------------------------------------------------------------------------------------------------------------
]]

AddConfig = {};

local currentModDirectory = g_currentModDirectory;

AddConfig.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 AddConfig.lua: " .. tostring(errorMessage));
end;

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

if ConfigurationUtil.sendNumBits < 27 then	
	ConfigurationUtil.sendNumBits = 27; --## = 134.217.728 possible configurations! I think, thats enough (2^27 = 134.217.728)!
	
	printError("Set max number of configurations to ".. g_i18n:formatNumber(2^ConfigurationUtil.sendNumBits), false, true);
end;

function AddConfig.prerequisitesPresent(specializations)
    return true;
end

function AddConfig:load(savegame)
	self.applyCustomDesing = Utils.overwrittenFunction(self.applyDesign, AddConfig.applyCustomDesing);
	
	local modDesc = loadXMLFile("modDesc", currentModDirectory .. "modDesc.xml");
	
	AddConfig.debugPriority = Utils.getNoNil(getXMLFloat(modDesc, "vehicle.newConfigurations#debugPriority"), AddConfig.debugPriority);
	
	local configNumber = 0;
	
	while true do
		local configKey = "modDesc.newConfigurations.newConfiguration(" .. tostring(configNumber) .. ")";
		
		if not hasXMLProperty(modDesc, configKey) then
			break;
		end;
		
		local isColorConfig = Utils.getNoNil(getXMLBool(modDesc, configKey .. "#isColorConfig"), false);
		local configName = getXMLString(modDesc, configKey .. "#configName");
		
		if configName ~= (nil and "") then
			if self.configurations[configName] ~= nil then	
				printDebug("Found configuration '" .. configName .. "' in vehicle '" .. self.configFileName .. "'.", 1, true);
				
				if isColorConfig then
					self:setColor(self.xmlFile, configName, self.configurations[configName]); --## config to change color on vehicle
					
					printDebug("Set color on vehichle '" .. self.configFileName .. "'.", 1, true);
				else
					self:applyCustomDesing(self.xmlFile, self.configurations[configName], configName); --## config to change texture on vehicle
					
					printDebug("Apply custom desing on vehichle '" .. self.configFileName .. "'.", 1, true);
				end;
			end;
		else
			printError("Missing the name for the new configuration in '" .. configKey .. "'! Stopping adding this config now!", false, false);
		end;
	
		configNumber = configNumber + 1;
	end;
	
	delete(modDesc);
end;

function AddConfig:preLoad(savegame)
	local modDesc = loadXMLFile("modDesc", currentModDirectory .. "modDesc.xml");
	local configNumber = 0;
	
	while true do
		local configKey = "modDesc.newConfigurations.newConfiguration(" .. tostring(configNumber) .. ")";
		
		if not hasXMLProperty(modDesc, configKey) then
			break;
		end;
		
		local configName = getXMLString(modDesc, configKey .. "#configName");
		
		if configName ~= (nil and "") then
			if self.configurations[configName] ~= nil then	
				local configKey = string.format("vehicle." .. configName .. "Configurations." .. configName .. "Configuration(%d)", self.configurations[configName] - 1);
				local newCapacity = getXMLFloat(self.xmlFile, configKey .. "#capacity");
				
				if newCapacity ~= nil then
					setXMLFloat(self.xmlFile, "vehicle.fillUnits.fillUnit(0)#capacity", newCapacity);
				end;
			end;
		end;
	
		configNumber = configNumber + 1;
	end;
	
	delete(modDesc);
end;

function AddConfig:applyCustomDesing(oldFunc, xmlFile, configId, configName)
    local configKey = string.format("vehicle." .. configName .. "Configurations." .. configName .. "Configuration(%d)", configId - 1);
    
    if not hasXMLProperty(xmlFile, configKey) then
        printError("Invalid '" .. configName .. "s' configuration (" .. configId .. ")", true, false);
        
	    return;
    end;
	
    --## change cutable fruit types
	
    local fruitTypes = {};
    local newFruitTypeCategories = getXMLString(self.xmlFile, configKey .. "#fruitTypeCategories");
    local newFruitTypeNames = getXMLString(self.xmlFile, configKey .. "#fruitTypes");
    local hasDeletedFruitTypes = false;
	
    if newFruitTypeCategories ~= nil and newFruitTypeNames == nil then
        fruitTypes = FruitUtil.getFruitTypeByCategoryName(newFruitTypeCategories);
    elseif newFruitTypeCategories == nil and newFruitTypeNames ~= nil then
        fruitTypes = FruitUtil.getFruitTypesByNames(newFruitTypeNames);
    end;

    if fruitTypes ~= nil then
	    for _, fruitType in pairs(fruitTypes) do
		    if not hasDeletedFruitTypes then
			    --## delete current cutable fruit types
				
				self.fruitTypes = {};
				
			    hasDeletedFruitTypes = true;
			end;

			local fruitTypeCheck = FillUtil.fillTypeIntToName[fruitType];

			if fruitTypeCheck ~= nil then	
				--## insert new cutable fruit types
				
				self.fruitTypes[fruitType] = true;
				
				printDebug("Insert fruit type '" .. fruitTypeCheck .. "' successfully to '" .. self.configFileName .. "'.", 1, true);
			end;
        end;
    end;
	
	--## change fillable fill types
	
	local fillTypes = {};
	local newFillTypeCategories = getXMLString(xmlFile, configKey .. "#fillTypeCategories");
	local newFillTypeNames = getXMLString(xmlFile, configKey .. "#fillTypes");
	local hasDeletedFillTypes = false;
	
	if newFillTypeCategories ~= nil and newFillTypeNames == nil then
		fillTypes = FillUtil.getFillTypeByCategoryName(newFillTypeCategories);
	elseif newFillTypeCategories == nil and newFillTypeNames ~= nil then
		fillTypes = FillUtil.getFillTypesByNames(newFillTypeNames);
	end;
	
	if fillTypes ~= nil then
		for _, fillType in pairs(fillTypes) do
			for _, fillUnit in pairs(self.fillUnits) do
				if not hasDeletedFillTypes then
					--## delete current fillable fill types
					
					fillUnit.fillTypes = {};
					
					hasDeletedFillTypes = true;
				end;
				
				local fillTypeCheck = FillUtil.fillTypeIntToName[fillType];
				
				if fillTypeCheck ~= nil then
					--## insert new fillable fill types
					
					fillUnit.fillTypes[fillType] = true;
					
					printDebug("Insert fill type '" .. fillTypeCheck .. "' successfully to '" .. self.configFileName .. "'.", 1, true);
				end;
			end;
		end;
	end;
	
	--## change capacity
    
	local newCapacity = getXMLFloat(xmlFile, configKey .. "#capacity");
	
	if newCapacity ~= nil then
		for _, fillUnit in pairs(self.fillUnits) do
			fillUnit.capacity = newCapacity;
			
			printDebug("Change capacity to: '" .. fillUnit.capacity .. "' successfully in '" .. self.configFileName .. "'.", 1, true);
		end;
	end;
	
	--## change rim and axis color
	
	local axisColor = getXMLString(xmlFile, configKey .. "#axisColor");
	local rimColor = getXMLString(xmlFile, configKey .. "#rimColor");
    
	for _, wheel in pairs(self.wheels) do
		if axisColor ~= nil then
			self.axisColor = Vehicle.getColorFromString(axisColor);
			
			if wheel.wheelHub ~= nil then
				local r, g, b, a = unpack(self.axisColor);
            
				setShaderParameter(wheel.wheelHub, "colorScale", r, g, b, a, false);
			
				printDebug("Change axis color to: " .. axisColor .. "' successfully in '" .. self.configFileName .. "'.", 1, true);
			end;
		end;
		
		if rimColor ~= nil then
			self.rimColor = Vehicle.getColorFromString(rimColor);
			
			local r, g, b, a = unpack(self.rimColor);
        
			if wheel.wheelOuterRim ~= nil then
				setShaderParameter(wheel.wheelOuterRim, "colorScale", r, g, b, a, false);
			
				printDebug("Change outer rim color to: " .. rimColor .. "' successfully in '" .. self.configFileName .. "'.", 1, true);
			end;
			
			if wheel.wheelInnerRim ~= nil then
				setShaderParameter(wheel.wheelInnerRim, "colorScale", r, g, b, a, false);
			
				printDebug("Change inner rim color to: " .. rimColor .. "' successfully in '" .. self.configFileName .. "'.", 1, true);
			end;
		end;
	end;
	
	--## change material
    
	local i = 0;
    
	while true do
        local materialKey = string.format(configKey .. ".material(%d)", i);
        
		if not hasXMLProperty(xmlFile, materialKey) then
            break;
        end;
        
		local baseMaterialNode = Utils.indexToObject(self.components, getXMLString(xmlFile, materialKey.."#node"));
        local refMaterialNode = Utils.indexToObject(self.components, getXMLString(xmlFile, materialKey.."#refNode"));
        
		if baseMaterialNode ~= nil and refMaterialNode ~= nil then
            local oldMaterial = getMaterial(baseMaterialNode, 0);
            local newMaterial = getMaterial(refMaterialNode, 0);
            
			for _, component in pairs(self.components) do
                self:replaceMaterialRec(component.node, oldMaterial, newMaterial);
				
				printDebug("Change material successfully in '" .. self.configFileName .. "'.", 1, true);
            end;
        end;
        
		i = i + 1;
    end;
    
	ObjectChangeUtil.updateObjectChanges(self.xmlFile, "vehicle." .. configName .. "Configurations." .. configName .. "Configuration", configId, self.components, self);
end;

function AddConfig:delete()end;
function AddConfig:mouseEvent(posX, posY, isDown, isUp, button)end;
function AddConfig:keyEvent(unicode, sym, modifier, isDown)end;
function AddConfig:update(dt)end;
function AddConfig:draw()end;

local modDesc = loadXMLFile("modDesc", currentModDirectory .. "modDesc.xml");
local configNumber = 0;
	
while true do
	local configKey = "modDesc.newConfigurations.newConfiguration(" .. tostring(configNumber) .. ")";
	
	if not hasXMLProperty(modDesc, configKey) then
		break;
	end;
	
	local isColorConfig = Utils.getNoNil(getXMLBool(modDesc, configKey .. "#isColorConfig"), false);
	local configName = getXMLString(modDesc, configKey .. "#configName");
	
	if configName ~= nil and configName ~= "" then
		if ConfigurationUtil.configurations[configName] == nil then
			if isColorConfig then
				ConfigurationUtil.registerConfigurationType(configName, g_i18n:getText("configuration_" .. configName), nil, Vehicle.getConfigColorSingleItemLoad, Vehicle.getConfigColorPostLoad, ConfigurationUtil.SELECTOR_COLOR); --## config to change color on vehicle
				
				printDebug("Register color configuration '" .. configName .."' successfully.", 1, true);
			else
				ConfigurationUtil.registerConfigurationType(configName, g_i18n:getText("configuration_" .. configName), nil, nil, nil, ConfigurationUtil.SELECTOR_MULTIOPTION); --## config to change parts on vehicle
				
				printDebug("Register desing configuration '" .. configName .."' successfully.", 1, true);
			end;
		end;
	else
		printError("Missing the name for the new Config in '" .. configKey .. "'! Stopping register this config now!", false, false);
	end;

	configNumber = configNumber + 1;
end;