--[[
HookLiftTrailerExtension

Script to allow set two unload animations on an HKL Truck/Trailer

@Author:	Ifko[nator]
@Date:		23.08.2019
@Version:	2.0

@History:	v1.0 @ 24.09.2017 - initial release in FS 17
			v2.0 @ 23.08.2019 - convert to FS 19
]]

HookLiftTrailerExtension = {};
HookLiftTrailerExtension.currentModName = g_currentModName;

function HookLiftTrailerExtension.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(HookLiftTrailer, specializations); 
end;

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

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

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

function HookLiftTrailerExtension.registerOverwrittenFunctions(vehicleType)
	local functionNames = {
		"getIsFoldAllowed"
	};
	
	for _, functionName in ipairs(functionNames) do
		SpecializationUtil.registerOverwrittenFunction(vehicleType, functionName, HookLiftTrailerExtension[functionName]);
	end;
end;

function HookLiftTrailerExtension:onLoad(savegame)
	local specHookLiftTrailer = self.spec_hookLiftTrailer;
	
	specHookLiftTrailer.unloadToTrailer = false;

	if savegame ~= nil then
		specHookLiftTrailer.unloadToTrailer = Utils.getNoNil(getXMLBool(savegame.xmlFile, savegame.key .. "." .. HookLiftTrailerExtension.currentModName .. ".hookLiftTrailerExtension#unloadToTrailer"), specHookLiftTrailer.unloadToTrailer);
	end;

	specHookLiftTrailer.unloadToTrailerOld = specHookLiftTrailer.unloadToTrailer;

	self:setUnloadState(specHookLiftTrailer.unloadToTrailer, false);

	specHookLiftTrailer.switchUnloadStateAnimation = Utils.getNoNil(getXMLString(self.xmlFile, "vehicle.hookLiftTrailer.switchUnloadStateAnimation#name"), "notDefined");
	specHookLiftTrailer.handRotPart = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, "vehicle.hookLiftTrailer.handRotPart#node"), self.i3dMappings);
	specHookLiftTrailer.unfoldHandToTrailerAnimation = Utils.getNoNil(getXMLString(self.xmlFile, "vehicle.hookLiftTrailer.unfoldHandToTrailerAnimation#name"), "unfoldHandToTrailer");
	specHookLiftTrailer.unfoldHandToGroundAnimation = specHookLiftTrailer.refAnimation;
end;

function HookLiftTrailerExtension:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
	local specHookLiftTrailer = self.spec_hookLiftTrailer;
	local specFoldable = self.spec_foldable;
	local changeUnloadingTypeButton = specHookLiftTrailer.actionEvents[InputAction.CHANGE_UNLOADING_TYPE_BUTTON];
	local currentText = g_i18n:getText("UNLOAD_TO_GROUND_IS_ACTIVE");

	specHookLiftTrailer.refAnimation = specHookLiftTrailer.unfoldHandToGroundAnimation;
	
	for _, foldingPart in pairs(specFoldable.foldingParts) do
		foldingPart.animationName = specHookLiftTrailer.unfoldHandToGroundAnimation;
	end;
	
	if specHookLiftTrailer.unloadToTrailer then
		currentText = g_i18n:getText("UNLOAD_TO_TRAILER_IS_ACTIVE");

		specHookLiftTrailer.refAnimation = specHookLiftTrailer.unfoldHandToTrailerAnimation;
	
		for _, foldingPart in pairs(specFoldable.foldingParts) do
			foldingPart.animationName = specHookLiftTrailer.unfoldHandToTrailerAnimation;
		end;
	end;

	if specHookLiftTrailer.switchUnloadStateAnimation ~= "notDefined" then
		local rotX, _, _ = getRotation(specHookLiftTrailer.handRotPart);

		--renderText(0.35, 0.5, 0.02, "rotX = " .. math.ceil(math.deg(rotX)));
		--renderText(0.35, 0.48, 0.02, "refAnimation time = " .. self:getAnimationTime(specHookLiftTrailer.refAnimation));
		
		local isArmUnfolded = rotX < 0 and not self:getIsAnimationPlaying(specHookLiftTrailer.refAnimation);
		local animDirection = -1;
		local currentRefAnimation = specHookLiftTrailer.unfoldHandToGroundAnimation;
		local oldRefAnimation = specHookLiftTrailer.unfoldHandToTrailerAnimation;

		if specHookLiftTrailer.unloadToTrailer then
			animDirection = 1;
			currentRefAnimation = specHookLiftTrailer.unfoldHandToTrailerAnimation;
			oldRefAnimation = specHookLiftTrailer.unfoldHandToGroundAnimation;
		end;

		--renderText(0.35, 0.46, 0.02, "isArmUnfolded = " .. tostring(isArmUnfolded));

		if isArmUnfolded then
			if specHookLiftTrailer.unloadToTrailerOld ~= specHookLiftTrailer.unloadToTrailer then
				self:playAnimation(specHookLiftTrailer.switchUnloadStateAnimation, animDirection, nil, true);

				specHookLiftTrailer.unloadToTrailerOld = specHookLiftTrailer.unloadToTrailer;
			end;
			
			if self:getAnimationTime(currentRefAnimation) == 0 and not self:getIsAnimationPlaying(specHookLiftTrailer.switchUnloadStateAnimation) then
				self:setAnimationTime(currentRefAnimation, 1);
			end;
		end;
		
		if rotX == 0 and not self:getIsAnimationPlaying(specHookLiftTrailer.refAnimation) then
			if self:getAnimationTime(oldRefAnimation) == 1 then
				self:setAnimationTime(oldRefAnimation, 0);
			end;

			if specHookLiftTrailer.unloadToTrailerOld ~= specHookLiftTrailer.unloadToTrailer then
				specHookLiftTrailer.unloadToTrailerOld = specHookLiftTrailer.unloadToTrailer;
			end;
		end;

		--renderText(0.35, 0.44, 0.02, "unloadToTrailerOld = " .. tostring(specHookLiftTrailer.unloadToTrailerOld));
		--renderText(0.35, 0.42, 0.02, "unloadToTrailer = " .. tostring(specHookLiftTrailer.unloadToTrailer));
		--renderText(0.35, 0.4, 0.02, "currentRefAnimation = " .. currentRefAnimation);
		--renderText(0.35, 0.38, 0.02, "is playing switch unload state = " .. tostring(self:getIsAnimationPlaying(specHookLiftTrailer.switchUnloadStateAnimation)));
	end;
	
	if changeUnloadingTypeButton ~= nil then
		local allowShowButton = not self:getIsAnimationPlaying(specHookLiftTrailer.refAnimation)
			and not self:getIsAnimationPlaying(specHookLiftTrailer.switchUnloadStateAnimation)
		;

		g_currentMission:addExtraPrintText(currentText);

		g_inputBinding:setActionEventActive(changeUnloadingTypeButton.actionEventId, allowShowButton);
		g_inputBinding:setActionEventTextVisibility(changeUnloadingTypeButton.actionEventId, allowShowButton);
	end;

	self:raiseActive();
end;

function HookLiftTrailerExtension:setUnloadState(unloadState, noEventSend)
	local specHookLiftTrailer = self.spec_hookLiftTrailer;

	if unloadState ~= specHookLiftTrailer.unloadToTrailer then	
		specHookLiftTrailer.unloadToTrailer = unloadState;
		
		HookLiftTrailerExtensionUnloadStateEvent.sendEvent(self, unloadState, noEventSend);
	end;
end;

function HookLiftTrailerExtension:getIsFoldAllowed(superFunc, direction, onAiTurnOn)
    local specHookLiftTrailer = self.spec_hookLiftTrailer;
	
	if self:getAnimationTime(specHookLiftTrailer.unloadingAnimation) > 0 or self:getIsAnimationPlaying(specHookLiftTrailer.switchUnloadStateAnimation) then
        return false;
	end;
	
    return superFunc(self, direction, onAiTurnOn);
end;

function HookLiftTrailerExtension:onWriteStream(streamId, connection)
	if not connection:getIsServer() then 
		local specHookLiftTrailer = self.spec_hookLiftTrailer;
		
		streamWriteBool(streamId, specHookLiftTrailer.unloadToTrailer);
	end;
end;

function HookLiftTrailerExtension:onReadStream(streamId, connection)
	if connection:getIsServer() then
		local specHookLiftTrailer = self.spec_hookLiftTrailer;
		
		specHookLiftTrailer.unloadToTrailer = streamReadBool(streamId);
	end;
end;

function HookLiftTrailerExtension:onRegisterActionEvents(isActiveForInput, isActiveForInputIgnoreSelection)
	if self.isClient then
        local specHookLiftTrailer = self.spec_hookLiftTrailer;
        
		self:clearActionEventsTable(specHookLiftTrailer.actionEvents);
        
		if self:getIsActiveForInput(true) then
			local newFunctions = {
				"CHANGE_UNLOADING_TYPE_BUTTON"
			};
			
			for _, newFunction in ipairs(newFunctions) do
				local _, actionEventId = self:addActionEvent(specHookLiftTrailer.actionEvents, InputAction[newFunction], self, HookLiftTrailerExtension.actionEventChangeUnloadState, false, true, false, true, nil);
			
				g_inputBinding:setActionEventTextPriority(actionEventId, GS_PRIO_NORMAL);
				g_inputBinding:setActionEventTextVisibility(actionEventId, true);
				g_inputBinding:setActionEventActive(actionEventId, true);
			end;
		end;
	end;
end;

function HookLiftTrailerExtension.actionEventChangeUnloadState(self, actionName, inputValue, callbackState, isAnalog)
	local specHookLiftTrailer = self.spec_hookLiftTrailer;

	self:setUnloadState(not specHookLiftTrailer.unloadToTrailer);
end;

function HookLiftTrailerExtension:saveToXMLFile(xmlFile, key)
	local specHookLiftTrailer = self.spec_hookLiftTrailer;
	local specBaler = self.spec_baler;
	
	setXMLBool(xmlFile, key .. "#unloadToTrailer", specHookLiftTrailer.unloadToTrailer);
end;

--## MP Stuff

--## set unload state

HookLiftTrailerExtensionUnloadStateEvent = {};
HookLiftTrailerExtensionUnloadStateEvent_mt = Class(HookLiftTrailerExtensionUnloadStateEvent, Event);

InitEventClass(HookLiftTrailerExtensionUnloadStateEvent, "HookLiftTrailerExtensionUnloadStateEvent");

function HookLiftTrailerExtensionUnloadStateEvent:emptyNew()
	local self = Event:new(HookLiftTrailerExtensionUnloadStateEvent_mt);
    
	return self;
end;

function HookLiftTrailerExtensionUnloadStateEvent:new(hookLiftTrailer, unloadState)
	local self = HookLiftTrailerExtensionUnloadStateEvent:emptyNew();
	
	self.hookLiftTrailer = hookLiftTrailer;
	self.unloadState = unloadState;
	
	return self;
end;

function HookLiftTrailerExtensionUnloadStateEvent:readStream(streamId, connection)
	self.hookLiftTrailer = NetworkUtil.readNodeObject(streamId);
	self.unloadState = streamReadBool(streamId);

    self:run(connection);
end;

function HookLiftTrailerExtensionUnloadStateEvent:writeStream(streamId, connection)
	NetworkUtil.writeNodeObject(streamId, self.hookLiftTrailer);
	streamWriteBool(streamId, self.unloadState);
end;

function HookLiftTrailerExtensionUnloadStateEvent:run(connection)
	self.hookLiftTrailer:setUnloadState(self.unloadState, true);
	
	if not connection:getIsServer() then
		g_server:broadcastEvent(HookLiftTrailerExtensionUnloadStateEvent:new(self.hookLiftTrailer, self.unloadState), nil, connection, self.hookLiftTrailer);
	end;
end;

function HookLiftTrailerExtensionUnloadStateEvent.sendEvent(hookLiftTrailer, unloadState, noEventSend)
	if noEventSend == nil or noEventSend == false then
		if g_server ~= nil then
			g_server:broadcastEvent(HookLiftTrailerExtensionUnloadStateEvent:new(hookLiftTrailer, unloadState), nil, nil, hookLiftTrailer);
		else
			g_client:getServerConnection():sendEvent(HookLiftTrailerExtensionUnloadStateEvent:new(hookLiftTrailer, unloadState));
		end;
	end;
end;