--[[Modauthor:		HoT online Team
	Creationdate:	16.08.22
	Version:		alpha 0.1.0
	Source:			Mill.lua for FS19 by derelky (v1.0 06.03.2019)
]]
cutwasher = {}
cutwasher.nameOfMod = g_currentModName

function cutwasher.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(FillUnit, specializations) and SpecializationUtil.hasSpecialization(Dischargeable, specializations)
end
function cutwasher.registerFunctions(vehicleType)
	SpecializationUtil.registerFunction(vehicleType, "additives", cutwasher.additives)
end
function cutwasher.registerOverwrittenFunctions(vehicleType)
	SpecializationUtil.registerOverwrittenFunction(vehicleType, "dischargeToGround", cutwasher.dischargeToGround)
	SpecializationUtil.registerOverwrittenFunction(vehicleType, "dischargeToObject", cutwasher.dischargeToObject)
end
function cutwasher.registerEventListeners(vehicleType)
    SpecializationUtil.registerEventListener(vehicleType, "onLoad", cutwasher)
end
function cutwasher.initSpecialization()
	local xmlschema = Vehicle.xmlSchema
	xmlschema:setXMLSpecializationType("cutwasher")
	xmlschema:register(XMLValueType.INT, "vehicle.cutwasher.additives#fillUnitIndex", "Additives fill unit")
	xmlschema:register(XMLValueType.FLOAT, "vehicle.cutwasher.additives#usage", "Usage per liter", 0.0000275)
	xmlschema:register(XMLValueType.FLOAT, "vehicle.cutwasher.additives#bonusrate", "Bonus rate", 1)
	xmlschema:register(XMLValueType.STRING, "vehicle.cutwasher.additives#fillTypes", "Filltypes to add to")
	xmlschema:setXMLSpecializationType()
end
function cutwasher.getSpecByName(self, specName, currentModName)
    local spec = self["spec_" .. Utils.getNoNil(currentModName, cutwasher.nameOfMod) .. "." .. specName];
	if spec ~= nil then
        return spec;
    end;
    return self["spec_" .. specName];
end;
function cutwasher:onLoad(savegame)
	local spec_cutwasher = cutwasher.getSpecByName(self, "cutwasher");
	spec_cutwasher.additives = {
		fillUnitIndex = self.xmlFile:getValue("vehicle.cutwasher.additives#fillUnitIndex")
	}
	spec_cutwasher.additives.available = self:getFillUnitByIndex(spec_cutwasher.additives.fillUnitIndex) ~= nil
	spec_cutwasher.additives.usage = self.xmlFile:getValue("vehicle.cutwasher.additives#usage", 0.0000275)
	spec_cutwasher.additives.bonusrate = self.xmlFile:getValue("vehicle.cutwasher.additives#bonusrate", 1)
	local additivesFillTypeNames = self.xmlFile:getValue("vehicle.cutwasher.additives#fillTypes")
	spec_cutwasher.additives.fillTypes = g_fillTypeManager:getFillTypesByNames(additivesFillTypeNames, "Warning: '" .. self.xmlFile:getFilename() .. "' has invalid fillType '%s'.")
end
function cutwasher:additives(FillType, origdroppedLiters, factor)
	local spec = cutwasher.getSpecByName(self, "cutwasher");
	local droppedLiters = origdroppedLiters * factor
	if self.isServer and spec.additives.available then
		local fillTypeSupported = false
		for i = 1, #spec.additives.fillTypes do
			if FillType == spec.additives.fillTypes[i] then
				fillTypeSupported = true
				break
			end
		end
		if fillTypeSupported then
			local additivesFillLevel = self:getFillUnitFillLevel(spec.additives.fillUnitIndex)
			if additivesFillLevel > 0 then
				local usage = spec.additives.usage * droppedLiters
				if usage > 0 then 
					local availableUsage = math.min(additivesFillLevel / usage, 1)
					droppedLiters = droppedLiters * (spec.additives.bonusrate * availableUsage)
					factor = droppedLiters/origdroppedLiters
					self:addFillUnitFillLevel(self:getOwnerFarmId(), spec.additives.fillUnitIndex, -usage, self:getFillUnitFillType(spec.additives.fillUnitIndex), ToolType.UNDEFINED)
				end
			end
		end
	end
	return droppedLiters, factor
end
function cutwasher:dischargeToGround(superFunc, dischargeNode, emptyLiters)
	if emptyLiters == 0 then
		return 0, false, false
	end
	local fillType, factor = self:getDischargeFillType(dischargeNode)
	local fillLevel = self:getFillUnitFillLevel(dischargeNode.fillUnitIndex)
	local minLiterToDrop = g_densityMapHeightManager:getMinValidLiterValue(fillType)
	dischargeNode.litersToDrop = math.min(dischargeNode.litersToDrop + emptyLiters, math.max(dischargeNode.emptySpeed * 250, minLiterToDrop))
	local minDropReached = minLiterToDrop < dischargeNode.litersToDrop
	local hasMinDropFillLevel = minLiterToDrop < fillLevel
	local info = dischargeNode.info
	local dischargedLiters = 0
	local sx, sy, sz = localToWorld(info.node, -info.width, 0, info.zOffset)
	local ex, ey, ez = localToWorld(info.node, info.width, 0, info.zOffset)
	sy = sy + info.yOffset
	ey = ey + info.yOffset
	if info.limitToGround then
		sy = math.max(getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, sx, 0, sz) + 0.1, sy)
		ey = math.max(getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, ex, 0, ez) + 0.1, ey)
	end
	local toDrop = dischargeNode.litersToDrop
	toDrop, factor = self:additives(fillType,dischargeNode.litersToDrop, factor)
	local dropped, lineOffset = DensityMapHeightUtil.tipToGroundAroundLine(self, toDrop, fillType, sx, sy, sz, ex, ey, ez, info.length, nil, dischargeNode.lineOffset, true, nil, true)
	dropped = dropped / factor
	dischargeNode.lineOffset = lineOffset
	dischargeNode.litersToDrop = dischargeNode.litersToDrop - dropped
	if dropped > 0 then
		local unloadInfo = self:getFillVolumeUnloadInfo(dischargeNode.unloadInfoIndex)
		dischargedLiters = self:addFillUnitFillLevel(self:getOwnerFarmId(), dischargeNode.fillUnitIndex, -dropped, self:getFillUnitFillType(dischargeNode.fillUnitIndex), ToolType.UNDEFINED, unloadInfo)
	end
	fillLevel = self:getFillUnitFillLevel(dischargeNode.fillUnitIndex)
	if fillLevel > 0 and fillLevel <= minLiterToDrop then
		dischargeNode.litersToDrop = minLiterToDrop
	end
	return dischargedLiters, minDropReached, hasMinDropFillLevel
end
function cutwasher:dischargeToObject(superFunc, dischargeNode, emptyLiters, object, targetFillUnitIndex)
	local fillType, factor = self:getDischargeFillType(dischargeNode)
	local supportsFillType = object:getFillUnitSupportsFillType(targetFillUnitIndex, fillType)
	local dischargedLiters = 0
	if supportsFillType then
		local allowFillType = object:getFillUnitAllowsFillType(targetFillUnitIndex, fillType)
		if allowFillType then
			dischargeNode.currentDischargeObject = object
			local toDrop = emptyLiters
			toDrop, factor = self:additives(fillType,emptyLiters, factor)
			local delta = object:addFillUnitFillLevel(self:getActiveFarm(), targetFillUnitIndex, toDrop, fillType, dischargeNode.toolType, dischargeNode.info)
			delta = delta / factor
			local unloadInfo = self:getFillVolumeUnloadInfo(dischargeNode.unloadInfoIndex)
			dischargedLiters = self:addFillUnitFillLevel(self:getOwnerFarmId(), dischargeNode.fillUnitIndex, -delta, self:getFillUnitFillType(dischargeNode.fillUnitIndex), ToolType.UNDEFINED, unloadInfo)
		end
	end
	return dischargedLiters
end