--[[
SupportArm

Specialization for manually controlled support arm.

Author:		Ifko[nator]
Datum:		11.08.2019

Version:	v1.0

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

SupportArm = {};
SupportArm.debugPriority = 0;

local function printError(errorMessage, isWarning, isInfo)
	local prefix = "::ERROR:: ";

	if isWarning then
		prefix = "::WARNING:: ";
	elseif isInfo then
		prefix = "::INFO:: ";
	end;

	print(prefix .. "from the SupportArm.lua: " .. tostring(errorMessage));
end;

local function printDebug(debugMessage, priority, addString)
	if SupportArm.debugPriority >= priority then
		local prefix = "";

		if addString then
			prefix = "::DEBUG:: from the SupportArm.lua: ";
		end;

		setFileLogPrefixTimestamp(false);
		print(prefix .. tostring(debugMessage));
		setFileLogPrefixTimestamp(true);
	end;
end;

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)
	local specAnimatedVehicle = self.spec_animatedVehicle;
	
	specAnimatedVehicle.supportArmAnimation = Utils.getNoNil(getXMLString(self.xmlFile, "vehicle.attachable.supportArm#animationName"), "notDefined");
	
	printDebug("support arm animation name = " .. specAnimatedVehicle.supportArmAnimation, 1, true);

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

function SupportArm:onRegisterActionEvents(isActiveForInput)
	if self.isClient then
		local specAnimatedVehicle = self.spec_animatedVehicle;
		
		self:clearActionEventsTable(specAnimatedVehicle.actionEvents);

		if self:getIsActiveForInput(true) then
            local newFunctions = {
				"PLAY_ANIMATION_BUTTON"
			};
			
			for _, newFunction in ipairs(newFunctions) do
				local _, actionEventId = self:addActionEvent(specAnimatedVehicle.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 specAnimatedVehicle = self.spec_animatedVehicle;

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

function SupportArm:setSupportArmState(isDown, noEventSend)
    local specAnimatedVehicle = self.spec_animatedVehicle;

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

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

		self:playAnimation(specAnimatedVehicle.supportArmAnimation, direction, nil, true);
	
		printDebug("specAnimatedVehicle.isDown = " .. tostring(specAnimatedVehicle.isDown), 1, true);
	
		specAnimatedVehicle.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 specAnimatedVehicle = self.spec_animatedVehicle;
		
		if specAnimatedVehicle.supportArmAnimation ~= "notDefined" then
			streamWriteBool(streamId, specAnimatedVehicle.isDown);
		end;
	end;
end;

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


function SupportArm:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
	local specAnimatedVehicle = self.spec_animatedVehicle;

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

				specAnimatedVehicle.isDown = false;
			end;

			specAnimatedVehicle.hasFinishedFirstRun = true;
		end;

		local playAnimationButton = specAnimatedVehicle.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 specAnimatedVehicle.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.baleWrapper);
	end;
	
    if self.trailer ~= nil then
        self.trailer:setSupportArmState(self.isDown, true);
	end;
end;