--[[
    AttachImplementEven

    Multiplayer Sync Event for attachments with deactivated attachImplementsManually function

	@author: 		BayernGamers
	@date: 			06.06.2025
	@version:		1.0

	History:		v1.0 @06.06.2025 - initial implementation in FS25
                    ------------------------------------------------------------------------------------------------------
	
	License:        Terms:
                        Usage:
                            Feel free to use this work as-is as long as you adhere to the following terms:
						Attribution:
							You must give appropriate credit to the original author when using this work.
						No Derivatives:
							You may not alter, transform, or build upon this work in any way.
						Usage: 
							The work may be used for personal and commercial purposes, provided it is not modified or adapted.
						Additional Clause:
							This script may not be converted, adapted, or incorporated into any other game versions or platforms except by GIANTS Software.
]]
source(Utils.getFilename("scripts/utils/Logger.lua", g_currentModDirectory))
source(Utils.getFilename("scripts/utils/ConnectionHoseUtil.lua", g_currentModDirectory))
source(Utils.getFilename("scripts/utils/PowerTakeOffUtil.lua", g_currentModDirectory))

AttachImplementEvent = {}

local log = Logger.new(true, Logger.DEBUG_LEVELS.HIGH, "AttachImplementEvent.lua")
local AttachImplementEvent_mt = Class(AttachImplementEvent, Event)

InitEventClass(AttachImplementEvent, "AttachImplementEvent")

function AttachImplementEvent:emptyNew()
    local self = Event.new(AttachImplementEvent_mt)
    return self
end

function AttachImplementEvent.new(vehicle, attachedVehicle, jointDescIndex, inputJointDescIndex, attachVehicle)
    local self = AttachImplementEvent:emptyNew()
    self.vehicle = vehicle
    self.attachedVehicle = attachedVehicle
    self.jointDescIndex = jointDescIndex
    self.inputJointDescIndex = inputJointDescIndex
    self.attachVehicle = attachVehicle

    return self
end

function AttachImplementEvent:writeStream(streamId, connection)
    NetworkUtil.writeNodeObject(streamId, self.vehicle)
    NetworkUtil.writeNodeObject(streamId, self.attachedVehicle)
    streamWriteInt8(streamId, self.jointDescIndex)
    streamWriteInt8(streamId, self.inputJointDescIndex)
    streamWriteBool(streamId, self.attachVehicle)
end

function AttachImplementEvent:readStream(streamId, connection)
    self.vehicle = NetworkUtil.readNodeObject(streamId)
    self.attachedVehicle = NetworkUtil.readNodeObject(streamId)
    self.jointDescIndex = streamReadInt8(streamId)
    self.inputJointDescIndex = streamReadInt8(streamId)
    self.attachVehicle = streamReadBool(streamId)

    self:run(connection)
end

function AttachImplementEvent:run(connection)
    if not connection:getIsServer() then
        g_server:broadcastEvent(self, false, nil, self.vehicle)
    end
    if self.vehicle ~= nil and self.attachedVehicle ~= nil then
        --[[
        local hasPTO = false
        --local hasConnectionHoses = false

        if SpecializationUtil.hasSpecialization(PowerTakeOffs, self.attachedVehicle.specializations) then
            local spec_powerTakeOffs = self.attachedVehicle.spec_powerTakeOffs

            hasPTO = #spec_powerTakeOffs.inputPowerTakeOffs > 0
        end
        ]]

        local jointDescIndex = self.jointDescIndex
        local inputAttacherJointIndex = self.inputJointDescIndex
        local hasPTO = PowerTakeOffUtil.getHasInputPTO(self.attachedVehicle, inputAttacherJointIndex) and PowerTakeOffUtil.getHasOutputPTO(self.vehicle, jointDescIndex)

        --[[
        if SpecializationUtil.hasSpecialization(ConnectionHoses, self.attachedVehicle.specializations) then
            local spec_connectionHoses = self.attachedVehicle.spec_connectionHoses

            hasConnectionHoses = #spec_connectionHoses.toolConnectorHoses > 0 or #spec_connectionHoses.hoseNodes > 0 or #spec_connectionHoses.customHoseTargets > 0 or #spec_connectionHoses.customHoses > 0 or #spec_connectionHoses.hoseSkipNodes > 0
        end
        ]]
        local hasConnectionHoses = ConnectionHoseUtil.getHasInputConnectionHoses(self.attachedVehicle, inputAttacherJointIndex)

        log:printDevInfo("hasInputPTO: " .. tostring(PowerTakeOffUtil.getHasInputPTO(self.attachedVehicle, inputAttacherJointIndex)), Logger.DEBUG_LEVELS.HIGH)
        log:printDevInfo("hasOutputPTO: " .. tostring(PowerTakeOffUtil.getHasOutputPTO(self.vehicle, jointDescIndex)), Logger.DEBUG_LEVELS.HIGH)
        log:printDevInfo("hasPTO: " .. tostring(hasPTO), Logger.DEBUG_LEVELS.HIGH)
        log:printDevInfo("hasConnectionHoses: " .. tostring(hasConnectionHoses), Logger.DEBUG_LEVELS.HIGH)

        if hasConnectionHoses then
            local spec_attachConnectionHosesManually = self.vehicle.spec_attachConnectionHosesManually
            local areHosesAttached = spec_attachConnectionHosesManually.attachedHoses[self.jointDescIndex] == true

            log:printDevInfo("areHosesAttached: " .. tostring(areHosesAttached), Logger.DEBUG_LEVELS.HIGH)
            log:printDevInfo("self.attachVehicle: " .. tostring(self.attachVehicle), Logger.DEBUG_LEVELS.HIGH)

            if (not self.attachVehicle and areHosesAttached) or (self.attachVehicle and not areHosesAttached) then
                log:printDevInfo("Toggling connection hose attach state", Logger.DEBUG_LEVELS.HIGH)
                self.vehicle:toggleConnectionHoseAttachState(self.attachedVehicle, self.jointDescIndex, self.inputJointDescIndex)
            end
        end

        if hasPTO then
            local spec_attachPowerTakeOffsManually = self.vehicle.spec_attachPowerTakeOffsManually
            local isPTOAttached = spec_attachPowerTakeOffsManually.attachedPTOs[self.jointDescIndex] == true

            log:printDevInfo("isPTOAttached: " .. tostring(isPTOAttached), Logger.DEBUG_LEVELS.HIGH)
             log:printDevInfo("self.attachVehicle: " .. tostring(self.attachVehicle), Logger.DEBUG_LEVELS.HIGH)

            if (not self.attachVehicle and isPTOAttached) or (self.attachVehicle and not isPTOAttached) then
                self.vehicle:togglePTOAttachState(self.attachedVehicle, self.jointDescIndex, self.inputJointDescIndex)
            end
        end
    end
end

function AttachImplementEvent.sendEvent(vehicle, attachedVehicle, jointDescIndex, inputJointDescIndex, attachVehicle, noEventSend)
    if noEventSend == nil or noEventSend == false then
        if g_server ~= nil then
            g_server:broadcastEvent(AttachImplementEvent.new(vehicle, attachedVehicle, jointDescIndex, inputJointDescIndex, attachVehicle), nil, nil, vehicle)
        else
            g_client:getServerConnection():sendEvent(AttachImplementEvent.new(vehicle, attachedVehicle, jointDescIndex, inputJointDescIndex, attachVehicle))
        end
    end
end