--
-- FS25 - Delimber
-- @author:    	kenny456 (kenny456@seznam.cz)
-- @history:	v1.0.0.0 - 2021-11-16 - first release
-- 				v1.0.0.0 - 2025-05-12 - FS5 conversion
--
Delimber = {}
Delimber.confDir = getUserProfileAppPath().. "modsSettings/Delimber/"
Delimber.modDirectory = g_currentModDirectory
local modName = g_currentModName
Delimber.showHelp = true

function Delimber.prerequisitesPresent(specializations)
	return true
end
function Delimber.initSpecialization()
    local schema = Vehicle.xmlSchema
    schema:setXMLSpecializationType("Delimber")
	
	schema:register(XMLValueType.NODE_INDEX, "vehicle.delimber.delimbNode#node", "Delimb node")
    schema:register(XMLValueType.FLOAT, "vehicle.delimber.delimbNode#sizeX", "Delimb size X", 0.1)
    schema:register(XMLValueType.FLOAT, "vehicle.delimber.delimbNode#sizeY", "Delimb size Y", 1)
    schema:register(XMLValueType.FLOAT, "vehicle.delimber.delimbNode#sizeZ", "Delimb size Z", 1)
    schema:register(XMLValueType.INT, "vehicle.delimber.delimbNode#effectTimer", "effect time", 1500)
    schema:register(XMLValueType.INT, "vehicle.delimber.delimbNode#delimbClawsMovingTool", "claws movingTool number", 1)
    EffectManager.registerEffectXMLPaths(schema, "vehicle.delimber.delimbEffects")
    schema:setXMLSpecializationType()

    local schemaSavegame = Vehicle.xmlSchemaSavegame
end
function Delimber.registerFunctions(vehicleType)
	SpecializationUtil.registerFunction(vehicleType, "getCanDelimb", Delimber.getCanDelimb)
end
function Delimber.registerEventListeners(vehicleType)
	for _,n in pairs( { "onLoad", "onPostLoad", "onDelete", "saveToXMLFile", "onUpdate", "onUpdateTick", "onDraw", "onReadStream", "onWriteStream"} ) do
		SpecializationUtil.registerEventListener(vehicleType, n, Delimber)
	end
end
function Delimber:onLoad(savegame)
	self.spec_delimber = {}
	local spec = self.spec_delimber
	
	local baseKey = "vehicle.delimber"
	spec.samples = {}
    spec.samples.delimb = g_soundManager:loadSampleFromXML(self.xmlFile.handle, baseKey..".sounds", "delimb", self.baseDirectory, self.components, 0, AudioGroup.VEHICLE, self.i3dMappings, self)
	spec.delimbEffects = g_effectManager:loadEffect(self.xmlFile, baseKey..".delimbEffects", self.components, self, self.i3dMappings)
	spec.delimbNode = self.xmlFile:getValue("vehicle.delimber.delimbNode#node", nil, self.components, self.i3dMappings)
    spec.delimbSizeX = self.xmlFile:getValue("vehicle.delimber.delimbNode#sizeX", 0.1)
    spec.delimbSizeY = self.xmlFile:getValue("vehicle.delimber.delimbNode#sizeY", 1)
    spec.delimbSizeZ = self.xmlFile:getValue("vehicle.delimber.delimbNode#sizeZ", 1)
    spec.effectTimer = self.xmlFile:getValue("vehicle.delimber.delimbNode#effectTimer", 1500)
    spec.delimbClawsMovingTool = self.xmlFile:getValue("vehicle.delimber.delimbNode#delimbClawsMovingTool", 1)
    spec.isDelimbSamplePlaying = false
	spec.isDelimbingForSound = false
	spec.delimbed = false
	spec.timerDelimbing = 0
	spec.infoText = ''
end
function Delimber:onPostLoad(savegame)
	local spec = self.spec_delimber

	spec.modInitialized = true
	spec.modAllowed = true
	if not spec.modInitialized then
		return
	end
end
function Delimber:onDelete()
	local spec = self.spec_delimber
	if not spec.modInitialized or not spec.modAllowed then
		return
	end
	g_effectManager:deleteEffects(spec.delimbEffects)
	g_soundManager:deleteSamples(spec.samples)
end
function Delimber:saveToXMLFile(xmlFile, key)
end
function Delimber:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
	local spec = self.spec_delimber
	if not spec.modInitialized or not spec.modAllowed then
		return
	end
	--spec.infoText = ''
	if self.isServer then
		if (spec.delimbNode ~= nil and spec.delimbSizeY ~= nil and spec.delimbSizeZ ~= nil) then
			if self:getCanDelimb() then
				local xD, yD, zD = getWorldTranslation(spec.delimbNode)
				local nxD, nyD, nzD = localDirectionToWorld(spec.delimbNode, 1, 0, 0)
				local yxD, yyD, yzD = localDirectionToWorld(spec.delimbNode, 0, 1, 0)
				spec.delimbed = findAndRemoveSplitShapeAttachments(xD, yD, zD, nxD, nyD, nzD, yxD, yyD, yzD, 0.7, spec.delimbSizeY, spec.delimbSizeZ)
				--print('spec.delimbed - '..tostring(spec.delimbed))
				if spec.delimbed then
					DelimberDelimbEvent.sendEvent(self, spec.delimbed, noEventSend)
				end
			end
		end
    end
	if spec.delimbed then
		spec.isDelimbingForSound = true
	end
	if spec.isDelimbingForSound then
		spec.timerDelimbing = spec.timerDelimbing + dt
		if spec.timerDelimbing >= spec.effectTimer then
			spec.isDelimbingForSound = false
			spec.timerDelimbing = 0
			spec.delimbed = false
		end
	end
	--[[spec.infoText = spec.infoText .. 'timerDelimbing - '..spec.timerDelimbing..'\n'
	spec.infoText = spec.infoText .. 'delimbed - '..tostring(spec.delimbed)..'\n'
	spec.infoText = spec.infoText .. 'isDelimbingForSound - '..tostring(spec.isDelimbingForSound)..'\n'
	spec.infoText = spec.infoText .. 'getCanDelimb - '..tostring(self:getCanDelimb())..'\n'
	spec.infoText = spec.infoText .. 'movingTools[1] - curRot'..tostring(self.spec_cylindered.movingTools[spec.delimbClawsMovingTool].curRot[3])..'\n'
	spec.infoText = spec.infoText .. 'movingTools[1] - rotMin'..tostring(self.spec_cylindered.movingTools[spec.delimbClawsMovingTool].rotMin)..'\n'
	spec.infoText = spec.infoText .. 'movingTools[1].rotSpeed - '..tostring(self.spec_cylindered.movingTools[spec.delimbClawsMovingTool].rotSpeed)..'\n'
	spec.infoText = spec.infoText .. 'movingTools[1].lastRotSpeed - '..tostring(self.spec_cylindered.movingTools[spec.delimbClawsMovingTool].lastRotSpeed)..'\n'
	spec.infoText = spec.infoText .. 'movingTools[1].move - '..tostring(self.spec_cylindered.movingTools[spec.delimbClawsMovingTool].move)..'\n'
	spec.infoText = spec.infoText .. 'massRoot - '..string.format('%.3f', getMass(self.rootNode)) ..'\n']]
	if self.isClient then
        -- delimb
        if spec.isDelimbingForSound then
            if not spec.isDelimbSamplePlaying then
                g_soundManager:playSample(spec.samples.delimb)
                spec.isDelimbSamplePlaying = true
            end
            g_effectManager:setEffectTypeInfo(spec.delimbEffects, FillType.WOODCHIPS)
            g_effectManager:startEffects(spec.delimbEffects)
        else
            if spec.isDelimbSamplePlaying then
                g_soundManager:stopSample(spec.samples.delimb)
                spec.isDelimbSamplePlaying = false
            end
            g_effectManager:stopEffects(spec.delimbEffects)
        end
    end
end
function Delimber:onUpdateTick(dt)
end
function Delimber:getCanDelimb()
	local spec = self.spec_delimber
	if not spec.modInitialized or not spec.modAllowed then
		return
	end
	
	local canDelimb = true
	if spec.delimbClawsMovingTool ~= nil and spec.delimbClawsMovingTool ~= 0 then
		if self.spec_cylindered.movingTools[spec.delimbClawsMovingTool] ~= nil then
			if self.spec_cylindered.movingTools[spec.delimbClawsMovingTool].curRot[3] < self.spec_cylindered.movingTools[spec.delimbClawsMovingTool].rotMin + 0.6 then
				canDelimb = false
			end
		end
	end
	return canDelimb
end
function Delimber:onDraw()
	local spec = self.spec_delimber
	if not spec.modInitialized or not spec.modAllowed then
		return
	end
	--renderText(0.69, 0.85, 0.013, spec.infoText)
end
function Delimber:onReadStream(streamId, connection)
	local spec = self.spec_delimber
	if not spec.modInitialized or not spec.modAllowed then
		return
	end
	spec.delimbed = streamReadBool(streamId)
end
function Delimber:onWriteStream(streamId, connection)
	local spec = self.spec_delimber
	if not spec.modInitialized or not spec.modAllowed then
		return
	end
	streamWriteBool(streamId, spec.delimbed)
end

DelimberDelimbEvent = {}
DelimberDelimbEvent_mt = Class(DelimberDelimbEvent, Event)

InitEventClass(DelimberDelimbEvent, "DelimberDelimbEvent")

function DelimberDelimbEvent.emptyNew()
    local self = Event.new(DelimberDelimbEvent_mt)
    self.className="DelimberDelimbEvent"
    return self
end

function DelimberDelimbEvent.new(object, delimbed)
	local self = DelimberDelimbEvent.emptyNew()
	self.object = object
	self.delimbed = delimbed
	return self
end

function DelimberDelimbEvent:readStream(streamId, connection)
	self.object = NetworkUtil.readNodeObject(streamId)
    self.delimbed = streamReadBool(streamId)
    self:run(connection)
end

function DelimberDelimbEvent:writeStream(streamId, connection)
	NetworkUtil.writeNodeObject(streamId, self.object)
	streamWriteBool(streamId, self.delimbed)
end

function DelimberDelimbEvent:run(connection)
	if self.object ~= nil then
		self.object.spec_delimber.delimbed = true
	end
	if not connection:getIsServer() then
		g_server:broadcastEvent(DelimberDelimbEvent.new(self.object, self.delimbed), nil, connection, self.object)
	end
end

function DelimberDelimbEvent.sendEvent(vehicle, delimbed, noEventSend)
	if noEventSend == nil or noEventSend == false then
		if g_server ~= nil then
			g_server:broadcastEvent(DelimberDelimbEvent.new(vehicle, delimbed), nil, nil, vehicle)
		else
			g_client:getServerConnection():sendEvent(DelimberDelimbEvent.new(vehicle, delimbed))
		end
	end
end
