MulcherMission = {};
MulcherMission.NAME = "mulcherMission";
MulcherMission.UI_SETTINGS = true;
MulcherMission.MAX_NUM_INSTANCE = 3;
MulcherMission.DEFAULT_NUM_INSTANCE = 2;
MulcherMission.BALANCE = {false,0};
MulcherMission.RANDOM = false;

source(AdditionalContracts.modDir.. "missions/mulcherMission/MulcherChangeSettingsEvent.lua");
source(AdditionalContracts.modDir.. "missions/mulcherMission/MulcherLoadSettingsEvent.lua");

MulcherMission.uiData = {
	settings = {
		mulcherMission_minMax = MulcherMission.DEFAULT_NUM_INSTANCE;
	};
	controls = {
		{ typName="mulcherMission", name="mulcherMission_minMax", autoBind=true, min=0, max=MulcherMission.MAX_NUM_INSTANCE, step=1, unit="/ ".. tostring(MulcherMission.MAX_NUM_INSTANCE), nillable=false };
	};
};

MulcherMission.data = {	
	ownTable = {FIELD_SIZE_BIGLARGE=30, classOverlay="tractor", typOverlay="weed"}; --big large multiple vehicles, 4x Mod Maps... / success factor for pf dlc	
	reward = {dismiss=0, min=2500, PER_HA=2000};
	jobTypName = g_i18n:getText("contract_field_mulcher_title");	
};

MulcherMission.metadata = {
	interface = "FS25 ...", --new
	title = "Mulching Contracts",
	notes = "Dieser Mod generiert Mulcher Aufträge.",
	author = "(by HappyLooser)",
	build = 5,
	datum = "10.07.2025",
	update = "01.11.2025",
	debugPrint = false, 
	discord = "HappyLooser Modding",
	info = " Link Freigabe,Änderungen,Kopien oder Code Benutzung ist ohne meine Zustimmung nicht erlaubt",
	"##Orginal Link Freigabe: https://www.farming-simulator.com/mods.php"
};

function debugPrint(text, ...)
	if MulcherMission.metadata.debugPrint then
		Logging.info(text,...);
	end;
end;

local MulcherMission_mt = Class(MulcherMission, AbstractFieldMission);
InitObjectClass(MulcherMission, "MulcherMission");

function MulcherMission.registerXMLPaths(schema, key)
	MulcherMission:superClass().registerXMLPaths(schema, key);
	schema:register(XMLValueType.INT, key .. "#rewardPerHa", "Reward per ha");
end;

function MulcherMission.registerSavegameXMLPaths(schema, key)
	MulcherMission:superClass().registerSavegameXMLPaths(schema, key);
	schema:register(XMLValueType.INT, key .. "#targetMulcherLevel", "Target mulcher level");
end;

function MulcherMission:saveToXMLFile(xmlFile, key)
	MulcherMission:superClass().saveToXMLFile(self, xmlFile, key);
	xmlFile:setValue(key .. "#targetMulcherLevel", self.targetMulcherLevel);
end;

function MulcherMission:loadFromXMLFile(xmlFile, key)
	if not MulcherMission:superClass().loadFromXMLFile(self, xmlFile, key) then
		return false;
	end;
	self.targetMulcherLevel = xmlFile:getValue(key .. "#targetMulcherLevel");
	return true;	
end;

function MulcherMission.new(isServer, isClient, customMt)
	local title = g_i18n:getText("contract_field_mulcher_title"); 
	local description = g_i18n:getText("contract_field_mulcher_description");
	local self = AbstractFieldMission.new(isServer, isClient, title, description, customMt or MulcherMission_mt);
	self.workAreaTypes = {
		[WorkAreaType.MULCHER] = true;
	}
	self.targetMulcherLevel = 0;
	self.fruitTypeIndex = nil;	
	return self;
end;

function MulcherMission:init(field, targetMulcherLevel)
	self.targetMulcherLevel = targetMulcherLevel;
	self.fruitTypeIndex = field:getFieldState().fruitTypeIndex;
	self:setMinReward();
	return MulcherMission:superClass().init(self, field);
end;

function MulcherMission:createModifier()	
	local mapId, firstChannel, numChannels = g_currentMission.fieldGroundSystem:getDensityMapData(FieldDensityMap.STUBBLE_SHRED_LEVEL);
	local levelState = FieldGroundType.getValueByType(FieldGroundType.STUBBLE_TILLAGE);	
	self.completionModifier = DensityMapModifier.new(mapId, firstChannel, numChannels, g_terrainNode);
	self.completionFilter = DensityMapFilter.new(self.completionModifier);	
	self.completionFilter:setValueCompareParams(DensityValueCompareType.EQUAL, levelState);	
end;

function MulcherMission:getFieldFinishTask()
	local fieldState = self.field:getFieldState();
	fieldState.stubbleShredLevel = self.targetMulcherLevel;	
	fieldState.fruitTypeIndex = FruitType.UNKNOWN;	
	fieldState.groundType = FieldGroundType.STUBBLE_TILLAGE;	
	debugPrint("f%s, growth %d, spray %s, sprayType %s, plow %s, lime %s, weed %s, roller %s, stubbleShredLevel %s, fruitTypeIndex %s, /getFieldFinishTask",
			self.field.farmland.name, fieldState.growthState, fieldState.sprayLevel, fieldState.sprayType, fieldState.plowLevel, fieldState.limeLevel, fieldState.weedState, fieldState.rollerLevel, fieldState.stubbleShredLevel, fieldState.fruitTypeIndex)
		
	return MulcherMission:superClass().getFieldFinishTask(self);
end;

function MulcherMission:getCompletion()
	return self:getFieldCompletion() / g_additionalContractTypes:getSuccessFactor();
	--if g_modIsLoaded.FS25_precisionFarming then
	--	return self:getFieldCompletion() / MulcherMission.data.ownTable.SUCCESS_FACTOR;
	--end;
	--return MulcherMission:superClass().getCompletion(self);	
end;

function MulcherMission:getVehicleVariant()	
	if self.field:getAreaHa() >= MulcherMission.data.ownTable.FIELD_SIZE_BIGLARGE then return "BIGLARGE";end; --big large multiple vehicles, 4x Mod Maps
	return "GRAIN";	
end;

function MulcherMission:getRewardPerHa()
	return g_missionManager:getMissionTypeDataByName(MulcherMission.NAME).rewardPerHa;
end;

function MulcherMission:setMinReward()
	if MulcherMission.data.reward.min == nil or MulcherMission.data.reward.min <= 0 then return;end;
	if self.reward < MulcherMission.data.reward.min then self.reward = MulcherMission.data.reward.min;end;	
end;

function MulcherMission:getMissionTypeName()
	return MulcherMission.NAME;
end;

function MulcherMission:validate(event)
	if MulcherMission:superClass().validate(self, event) then
		return (self:getIsFinished() or MulcherMission.isAvailableForField(self.field, self)) and true or false;
	else
		return false;
	end;
end;

function MulcherMission.loadMapData(xmlFile, key, baseDirectory)	
	local data = g_missionManager:getMissionTypeDataByName(MulcherMission.NAME);
	data.rewardPerHa = xmlFile:getFloat(key .. "#rewardPerHa", MulcherMission.data.reward.PER_HA);
	return true;
end;

function MulcherMission.tryGenerateMission(addConsole)
	if MulcherMission.canRun(addConsole) then
		local field = g_fieldManager:getFieldForMission();
		if field == nil then
			if addConsole then printError("Error: No found mission field");end;
			return;
		end;
		if field.currentMission ~= nil then
			if addConsole then printError("Error: Field currentMission already");end;
			return;
		end;
		if not MulcherMission.isAvailableForField(field, nil) then
			if addConsole then printError("Error: No found isAvailableForField");end;
			return;
		end;
		local mulcherLevel = field:getFieldState().stubbleShredLevel + 1
		local mission = MulcherMission.new(true, g_client ~= nil);
		if mission:init(field, mulcherLevel) then
			mission:setDefaultEndDate();
			return mission;
		end;
		if addConsole then printError("Error: Mission init not true");end;
		mission:delete();
	end;
	if addConsole then printError("Error: Mission type not active or disabled");end;
	return nil;
end;

function MulcherMission.isAvailableForField(field, mission)
	if mission == nil then
		if field == nil or field.getFieldState == nil then return false;end;
		local fieldState = field:getFieldState();
		if not fieldState.isValid then
			return false;
		end;
		if field.grassMissionOnly then
			return false;
		end;				
		debugPrint("f%s, growth %d, spray %s, sprayType %s, plow %s, lime %s, weed %s, roller %s, stubbleShredLevel %s, fruitTypeIndex %s, /isAvailableForField",
			field.farmland.name, fieldState.growthState, fieldState.sprayLevel, fieldState.sprayType, fieldState.plowLevel, fieldState.limeLevel, fieldState.weedState, fieldState.rollerLevel, fieldState.stubbleShredLevel, fieldState.fruitTypeIndex)
		if fieldState.stubbleShredLevel == nil or fieldState.stubbleShredLevel > 0 then 
			return false;
		end;
		local fruitIndex = fieldState.fruitTypeIndex;
		if fruitIndex == FruitType.UNKNOWN then
			return false;
		end;
		local growthState = fieldState.growthState;
		local fruitDesc = g_fruitTypeManager:getFruitTypeByIndex(fruitIndex);		
		if fruitDesc == nil or (fruitDesc:getIsCatchCrop() and growthState <= 1) then return false;end;
		if not fruitDesc:getIsCut(growthState) or fruitDesc:getIsWithered(growthState) then return false;end;		
	end;
	return true;
end;

function MulcherMission.canRun(addConsole)
	if not MulcherMission:getOnOff() then return false;end;
	if addConsole then return true;end;
	local data = g_missionManager:getMissionTypeDataByName(MulcherMission.NAME);	
	if data.numInstances >= data.maxNumInstances or data.numInstances >= g_additionalContractTypes.settings[MulcherMission.NAME.. "_minMax"] then
		return false;
	else
		return true; --not g_currentMission.growthSystem:getIsGrowingInProgress();
	end;
end;

function MulcherMission:setMaxNumInstance(maxNumInstance)
	self.uiData.settings[MulcherMission.NAME.. "_minMax"] = maxNumInstance;
	g_additionalContractTypes:replaceUISettings(MulcherMission.NAME.. "_minMax", maxNumInstance);
	local data = g_missionManager:getMissionTypeDataByName(MulcherMission.NAME);
	if data ~= nil then data.maxNumInstances = maxNumInstance;end;	
end;

function MulcherMission:getMaxNumInstance()
	local data = g_missionManager:getMissionTypeDataByName(MulcherMission.NAME);
	if data == nil then 
		return g_additionalContractTypes.settings[MulcherMission.NAME.. "_minMax"];
	end;
	return data.maxNumInstances;
end;

function MulcherMission:getOnOff()
	return g_additionalContractTypes.settings[MulcherMission.NAME.. "_minMax"] > 0;
end;

function MulcherMission:setOnOff(state)
	
end;

function MulcherMission:canBalance()
	return MulcherMission.BALANCE[1];
end;

function MulcherMission:getBalance()
	return MulcherMission.BALANCE[2];
end;

function MulcherMission:setBalance(state)
	MulcherMission.BALANCE[2] = state or MulcherMission.BALANCE[2] + 1;
end;

function MulcherMission:canRandom()
	return MulcherMission.RANDOM;
end;

function MulcherMission:setRandom(state)
	MulcherMission.RANDOM = state or not MulcherMission.RANDOM;
end;

function MulcherMission:getJobTypName()
	return self.data.jobTypName;
end;

function MulcherMission:onStartMap(args)
	if not args.isDetiServer and FS25_MissionsExpanded ~= nil and FS25_MissionsExpanded.MissionsExpanded ~= nil and FS25_MissionsExpanded.MissionsExpanded.missionsMultiplier["mulcherMission"] ~= nil then --replace MissionsExpanded value
		FS25_MissionsExpanded.MissionsExpanded.missionsMultiplier["mulcherMission"][1] = g_additionalContractTypes.settings[MulcherMission.NAME.. "_minMax"];
		local data = g_missionManager:getMissionTypeDataByName(MulcherMission.NAME);
		if data ~= nil and data.maxNumInstances ~= g_additionalContractTypes.settings[MulcherMission.NAME.. "_minMax"] then data.maxNumInstances = g_additionalContractTypes.settings[MulcherMission.NAME.. "_minMax"];end; 
	end;
end;

function MulcherMission:loadInit()	
	if MulcherMission.UI_SETTINGS then		
		local isReady = false;
		for key, value in pairs(MulcherMission.uiData.settings) do			
			isReady = g_additionalContractTypes:setUISettings(key, value);
			if not isReady then break;end; 
		end;
		if isReady then
			for _, control in ipairs(MulcherMission.uiData.controls) do
				g_additionalContractTypes:setUIControls(control);			
			end;
		else
			for key, value in pairs(MulcherMission.uiData.settings) do
				g_additionalContractTypes:delUISettings(key);				 
			end;
		end;		
	end;
	local xmlFile = Utils.getFilename("missionVehicles/mulcherMissionVehicles.xml", AdditionalContracts.modDir)
	g_missionManager:addPendingMissionVehiclesFile(xmlFile, AdditionalContracts.modDir)
end;

function MulcherMission:loadSettingsEvent(mission, connection, x, y, z, viewDistanceCoeff)
	if g_currentMission ~= nil and g_currentMission.missionDynamicInfo ~= nil and g_currentMission.missionDynamicInfo.isMultiplayer then
		g_client:getServerConnection():sendEvent(MulcherLoadSettingsEvent.new());
	end;
end;

function MulcherMission:changeSettingsEvent(settingsId, state)
	if g_currentMission ~= nil and g_currentMission.missionDynamicInfo ~= nil and g_currentMission.missionDynamicInfo.isMultiplayer then
		g_client:getServerConnection():sendEvent(MulcherChangeSettingsEvent.new(settingsId, state));
	else
		self:onChangeSettings(settingsId, state);
	end;
end;

function MulcherMission:onChangeSettings(settingsId, state)
	if settingsId == "mulcherMission_minMax" then		
		self:setMaxNumInstance(state);		
	end;	
end;

function MulcherMission:loadSettingsXML(xmlFile, prefix) 	
	if not xmlFile:hasProperty(prefix.. ".".. MulcherMission.NAME.. ".minMax") then return;end;	
	local minMax = xmlFile:getInt(prefix.. ".".. MulcherMission.NAME.. ".minMax");
	local control = g_additionalContractTypes:getUIControls(MulcherMission.NAME.. "_minMax");
	if minMax > control.max then minMax = control.max;elseif minMax < control.min then minMax = control.min;end;	
	self:setMaxNumInstance(minMax);	
end;

function MulcherMission:saveSettingsXML(xmlFile, prefix)    
	xmlFile:setInt(prefix.. ".".. MulcherMission.NAME.. ".minMax", g_additionalContractTypes.settings[MulcherMission.NAME.. "_minMax"]);
end;

function MulcherMission:getClassTypOverlay(args)
	local classOverlay = "tractor";
	local typOverlay = "weed";
	if self.data.ownTable.classOverlay ~= nil then classOverlay = self.data.ownTable.classOverlay;end;
	if self.data.ownTable.typOverlay ~= nil then typOverlay = self.data.ownTable.typOverlay;end;	
	return classOverlay, typOverlay;
end;

function MulcherMission:getFillTypeIndexOverlay(args)
	return nil, "fillType_field";
end;

g_additionalContractTypes:registerTyp(MulcherMission, MulcherMission.NAME, true);
