--[[
SupportArm

Specialization for manually controlled support arm.

Author:		Ifko[nator]
Datum:		09.02.2020

Version:	v1.0

History:	v1.0 @ 09.02.2020 - initial implementation in FS 19
			---------------------------------------------------
]]

SupportArm = {};

function SupportArm.prerequisitesPresent(specializations)
    return true;
end;

function SupportArm.registerFunctions(vehicleType)
	local functionNames = {
		"setSupportArmState"
	};
	
	for _, functionName in ipairs(functionNames) do
		SpecializationUtil.registerFunction(vehicleType, functionName, SupportArm[functionName]);
	end;
end;


function SupportArm.registerEventListeners(vehicleType)
	local functionNames = {
		"onLoad",
		"onUpdate",
		"onWriteStream",
		"onReadStream",
		"onRegisterActionEvents"
	};

	for _, functionName in ipairs(functionNames) do
		SpecializationUtil.registerEventListener(vehicleType, functionName, SupportArm);
	end;
end;

function SupportArm:onLoad(savegame)
	if FlieglTransportPackUtil == nil then
        return;
	end;

	SupportArm.debugPriority = FlieglTransportPackUtil.getDebugPriority(self.xmlFile, "vehicle.attachable.supportArm#debugPriority");

	local specSupportArm = FlieglTransportPackUtil.getSpecByName(self, "supportArm");
	
	specSupportArm.supportArmAnimation = Utils.getNoNil(getXMLString(self.xmlFile, "vehicle.attachable.supportArm#animationName"), "notDefined");
	
	FlieglTransportPackUtil.printDebug("support arm animation name = " .. specSupportArm.supportArmAnimation, SupportArm.debugPriority, true, "SupportArm");

	if specSupportArm.supportArmAnimation ~= "notDefined" then	
		specSupportArm.isDown = true;
		specSupportArm.hasFinishedFirstRun = false;
	end;
end;

function SupportArm:onRegisterActionEvents(isActiveForInput)
	if self.isClient then
		local specSupportArm = FlieglTransportPackUtil.getSpecByName(self, "supportArm");
		
		self:clearActionEventsTable(specSupportArm.actionEvents);

		if self:getIsActiveForInput(true) then
            local newFunctions = {
				"PLAY_ANIMATION_BUTTON"
			};
			
			for _, newFunction in ipairs(newFunctions) do
				local _, actionEventId = self:addActionEvent(specSupportArm.actionEvents, InputAction[newFunction], self, SupportArm.actionEventPlayAnimation, false, true, false, true, nil);
			
				g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_HIGH);
				g_inputBinding:setActionEventTextVisibility(actionEventId, true);
				g_inputBinding:setActionEventActive(actionEventId, false);
			end;
		end;
	end;
end;

function SupportArm:actionEventPlayAnimation(actionName, inputValue, callbackState, isAnalog)
	local specSupportArm = FlieglTransportPackUtil.getSpecByName(self, "supportArm");

	if specSupportArm ~= nil and specSupportArm.supportArmAnimation ~= "notDefined" then
		self:setSupportArmState(not specSupportArm.isDown);
	end;
end;

function SupportArm:setSupportArmState(isDown, noEventSend)
    local specSupportArm = FlieglTransportPackUtil.getSpecByName(self, "supportArm");

	if isDown ~= specSupportArm.isDown then
		local direction = 1;

		if specSupportArm.isDown then
			direction = -1;
		end;

		self:playAnimation(specSupportArm.supportArmAnimation, direction, nil, true);
	
		FlieglTransportPackUtil.printDebug("specSupportArm.isDown = " .. tostring(specSupportArm.isDown), SupportArm.debugPriority, true, "SupportArm");
	
		specSupportArm.isDown = isDown;
		
		if not noEventSend then
			if g_server ~= nil then
				g_server:broadcastEvent(SetSupportArmStateEvent:new(self, isDown), nil, nil, self);
			else
				g_client:getServerConnection():sendEvent(SetSupportArmStateEvent:new(self, isDown));
			end;
		end;
	end;
end;


function SupportArm:onWriteStream(streamId, connection)
	if not connection:getIsServer() then 
		local specSupportArm = FlieglTransportPackUtil.getSpecByName(self, "supportArm");
		
		if specSupportArm.supportArmAnimation ~= "notDefined" then
			streamWriteBool(streamId, specSupportArm.isDown);
		end;
	end;
end;

function SupportArm:onReadStream(streamId, connection)
	if connection:getIsServer() then
		local specSupportArm = FlieglTransportPackUtil.getSpecByName(self, "supportArm");
		
		if specSupportArm.supportArmAnimation ~= "notDefined" then
			specSupportArm.isDown = streamReadBool(streamId);
		end;
	end;
end;


function SupportArm:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
	local specSupportArm = FlieglTransportPackUtil.getSpecByName(self, "supportArm");

	if specSupportArm.supportArmAnimation ~= "notDefined" then
		if not specSupportArm.hasFinishedFirstRun then	
			local specAttachable = self.spec_attachable;
			
			FlieglTransportPackUtil.printDebug("specAttachable.attacherVehicle = " .. tostring(specAttachable.attacherVehicle) .. "(configFileName) " .. self.configFileName, SupportArm.debugPriority, true, "SupportArm");
			
			if specAttachable.attacherVehicle ~= nil then
				self:playAnimation(specSupportArm.supportArmAnimation, -1, nil, true);
				AnimatedVehicle.updateAnimationByName(self, specSupportArm.supportArmAnimation, 9999999);

				specSupportArm.isDown = false;
			end;

			specSupportArm.hasFinishedFirstRun = true;
		end;

		local playAnimationButton = specSupportArm.actionEvents[InputAction.PLAY_ANIMATION_BUTTON];

		if playAnimationButton ~= nil then
			local currentText = g_i18n:getText("MOVE_SUPPORT_ARM_DOWN");

			g_inputBinding:setActionEventActive(playAnimationButton.actionEventId, true);

			if specSupportArm.isDown then
				currentText = g_i18n:getText("MOVE_SUPPORT_ARM_UP");
			end;

			g_inputBinding:setActionEventText(playAnimationButton.actionEventId, currentText);
		end;
	end;
end;

SetSupportArmStateEvent = {};
SetSupportArmStateEvent_mt = Class(SetSupportArmStateEvent, Event);

InitEventClass(SetSupportArmStateEvent, "SetSupportArmStateEvent");

function SetSupportArmStateEvent:emptyNew()
	local self = Event:new(SetSupportArmStateEvent_mt);
    
	return self;
end;

function SetSupportArmStateEvent:new(trailer, isDown)
	local self = SetSupportArmStateEvent:emptyNew();
	
	self.trailer = trailer;
	self.isDown = isDown;
	
	return self;
end;

function SetSupportArmStateEvent:readStream(streamId, connection)
	self.trailer = NetworkUtil.readNodeObject(streamId);
	self.isDown = streamReadBool(streamId);
    
	self:run(connection);
end;

function SetSupportArmStateEvent:writeStream(streamId, connection)
	NetworkUtil.writeNodeObject(streamId, self.trailer);
	streamWriteBool(streamId, self.isDown);
end;

function SetSupportArmStateEvent:run(connection)
	if not connection:getIsServer() then
		g_server:broadcastEvent(SetSupportArmStateEvent:new(self.trailer, self.isDown), nil, connection, self.trailer);
	end;
	
    if self.trailer ~= nil then
        self.trailer:setSupportArmState(self.isDown, true);
	end;
end;