--[[
ExtendedManureSpreader

Specialization for extended manure spreader functions

Author:		Ifko[nator]
Datum:		09.02.2020

Version:	v1.0

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

ExtendedManureSpreader = {};
ExtendedManureSpreader.currentModName = g_currentModName;

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

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


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

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

function ExtendedManureSpreader:onLoad(savegame)
	if FlieglTransportPackUtil == nil then
        return;
	end;
	
	ExtendedManureSpreader.debugPriority = FlieglTransportPackUtil.getDebugPriority(self.xmlFile, "vehicle.sprayer.animations#debugPriority");

	local specExtendedManureSpreader = FlieglTransportPackUtil.getSpecByName(self, "extendedManureSpreader");
	local specAnimatedVehicle = FlieglTransportPackUtil.getSpecByName(self, "animatedVehicle");
	
	specExtendedManureSpreader.hasSetCapacity = false;
	specExtendedManureSpreader.capacityBackup = self:getFillUnitCapacity(1);
	specExtendedManureSpreader.door = {};
	specExtendedManureSpreader.door.animations = {};
	specExtendedManureSpreader.door.animations.left = Utils.getNoNil(getXMLString(self.xmlFile, "vehicle.sprayer.animations.left#animationName"), "notDefined");
	specExtendedManureSpreader.door.animations.right = Utils.getNoNil(getXMLString(self.xmlFile, "vehicle.sprayer.animations.right#animationName"), "notDefined");
	
	FlieglTransportPackUtil.printDebug("door animation left animation name = " .. specExtendedManureSpreader.door.animations.left, ExtendedManureSpreader.debugPriority, true, "ExtendedManureSpreader");
	FlieglTransportPackUtil.printDebug("door animation right animation name = " .. specExtendedManureSpreader.door.animations.right, ExtendedManureSpreader.debugPriority, true, "ExtendedManureSpreader");

	if specAnimatedVehicle.animations[specExtendedManureSpreader.door.animations.left] == nil then
		FlieglTransportPackUtil.printError("missing door animation left (animation name = " .. specExtendedManureSpreader.door.animations.left .. ")! This Animation will not work!", false, false, "ExtendedManureSpreader");
		
		specExtendedManureSpreader.door.animations.left = "notDefined";
	end;

	if specAnimatedVehicle.animations[specExtendedManureSpreader.door.animations.right] == nil then
		FlieglTransportPackUtil.printError("missing door animation right (animation name = " .. specExtendedManureSpreader.door.animations.right .. ")! This Animation will not work!", false, false, "ExtendedManureSpreader");
		
		specExtendedManureSpreader.door.animations.right = "notDefined";
	end;

	if specExtendedManureSpreader.door.animations.left ~= "notDefined" then	
		specExtendedManureSpreader.leftIsClosed = true;

		if savegame ~= nil then
			specExtendedManureSpreader.leftIsClosed = Utils.getNoNil(getXMLBool(savegame.xmlFile, savegame.key .. "." .. ExtendedManureSpreader.currentModName .. ".extendedManureSpreader#leftIsClosed"), specExtendedManureSpreader.leftIsClosed);
		end;

		self:setLeftDoorState(specExtendedManureSpreader.leftIsClosed);
	end;

	if specExtendedManureSpreader.door.animations.right ~= "notDefined" then	
		specExtendedManureSpreader.rightIsClosed = true;

		if savegame ~= nil then
			specExtendedManureSpreader.rightIsClosed = Utils.getNoNil(getXMLBool(savegame.xmlFile, savegame.key .. "." .. ExtendedManureSpreader.currentModName .. ".extendedManureSpreader#rightIsClosed"), specExtendedManureSpreader.rightIsClosed);
		end;

		self:setRightDoorState(specExtendedManureSpreader.rightIsClosed);
	end;
end;

function ExtendedManureSpreader:onRegisterActionEvents(isActiveForInput)
	if self.isClient then
		local specExtendedManureSpreader = FlieglTransportPackUtil.getSpecByName(self, "extendedManureSpreader");

		self:clearActionEventsTable(specExtendedManureSpreader.actionEvents);

		if self:getIsActiveForInput(true) then
            local newFunctions = {
				"OPEN_LEFT_DOOR_BUTTON",
				"OPEN_RIGHT_DOOR_BUTTON"
			};
			
			for _, newFunction in ipairs(newFunctions) do
				local _, actionEventId = self:addActionEvent(specExtendedManureSpreader.actionEvents, InputAction[newFunction], self, ExtendedManureSpreader.actionEventOpenAnimation, 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 ExtendedManureSpreader:actionEventOpenAnimation(actionName, inputValue, callbackState, isAnalog)
	local specExtendedManureSpreader = FlieglTransportPackUtil.getSpecByName(self, "extendedManureSpreader");

	if specExtendedManureSpreader ~= nil then
		if actionName == "OPEN_LEFT_DOOR_BUTTON" then
			if specExtendedManureSpreader.door.animations.left ~= "notDefined" then
				self:setLeftDoorState(not specExtendedManureSpreader.leftIsClosed);
			end;
		else
			if specExtendedManureSpreader.door.animations.right ~= "notDefined" then
				self:setRightDoorState(not specExtendedManureSpreader.rightIsClosed);
			end;
		end;
	end;
end;

function ExtendedManureSpreader:setLeftDoorState(leftIsClosed, noEventSend)
    local specExtendedManureSpreader = FlieglTransportPackUtil.getSpecByName(self, "extendedManureSpreader");

	if leftIsClosed ~= specExtendedManureSpreader.leftIsClosed then
		local direction = -1;

		if specExtendedManureSpreader.leftIsClosed then
			direction = 1;
		end;

		self:playAnimation(specExtendedManureSpreader.door.animations.left, direction, nil, true);
	
		FlieglTransportPackUtil.printDebug("specExtendedManureSpreader.leftIsClosed = " .. tostring(specExtendedManureSpreader.leftIsClosed), ExtendedManureSpreader.debugPriority, true, "ExtendedManureSpreader");
	
		specExtendedManureSpreader.leftIsClosed = leftIsClosed;
		
		SetLeftDoorStateEvent.sendEvent(self, leftIsClosed, noEventSend);
	end;
end;

function ExtendedManureSpreader:setRightDoorState(rightIsClosed, noEventSend)
    local specExtendedManureSpreader = FlieglTransportPackUtil.getSpecByName(self, "extendedManureSpreader");

	if rightIsClosed ~= specExtendedManureSpreader.rightIsClosed then
		local direction = -1;

		if specExtendedManureSpreader.rightIsClosed then
			direction = 1;
		end;

		self:playAnimation(specExtendedManureSpreader.door.animations.right, direction, nil, true);
	
		FlieglTransportPackUtil.printDebug("specExtendedManureSpreader.rightIsClosed = " .. tostring(specExtendedManureSpreader.rightIsClosed), ExtendedManureSpreader.debugPriority, true, "ExtendedManureSpreader");
	
		specExtendedManureSpreader.rightIsClosed = rightIsClosed;

		SetRightDoorStateEvent.sendEvent(self, rightIsClosed, noEventSend);
	end;
end;

function ExtendedManureSpreader:onWriteStream(streamId, connection)
	if not connection:getIsServer() then 
		local specExtendedManureSpreader = FlieglTransportPackUtil.getSpecByName(self, "extendedManureSpreader");
		
		if specExtendedManureSpreader.door.animations.left ~= "notDefined" then
			streamWriteBool(streamId, specExtendedManureSpreader.leftIsClosed);
		end;

		if specExtendedManureSpreader.door.animations.right ~= "notDefined" then
			streamWriteBool(streamId, specExtendedManureSpreader.rightIsClosed);
		end;
	end;
end;

function ExtendedManureSpreader:onReadStream(streamId, connection)
	if connection:getIsServer() then
		local specExtendedManureSpreader = FlieglTransportPackUtil.getSpecByName(self, "extendedManureSpreader");
		
		if specExtendedManureSpreader.door.animations.left ~= "notDefined" then
			specExtendedManureSpreader.leftIsClosed = streamReadBool(streamId);
		end;

		if specExtendedManureSpreader.door.animations.right ~= "notDefined" then
			specExtendedManureSpreader.rightIsClosed = streamReadBool(streamId);
		end;
	end;
end;

function ExtendedManureSpreader:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
	local specExtendedManureSpreader = FlieglTransportPackUtil.getSpecByName(self, "extendedManureSpreader");
	local specFillUnit = FlieglTransportPackUtil.getSpecByName(self, "fillUnit");
	
	local multiplier = 1;

	if not specExtendedManureSpreader.leftIsClosed or not specExtendedManureSpreader.rightIsClosed then
		if not specExtendedManureSpreader.hasSetCapacity then
			self:setFillUnitCapacity(1, math.floor(self:getFillUnitCapacity(1) / 2));

			specExtendedManureSpreader.hasSetCapacity = true;
		end;

		multiplier = 2;
	else
		if specExtendedManureSpreader.hasSetCapacity then	
			self:setFillUnitCapacity(1, specExtendedManureSpreader.capacityBackup);

			specExtendedManureSpreader.hasSetCapacity = false;
		end;
	end;

	local fillLevel = FlieglTransportPackUtil.getFillLevel(specFillUnit.fillUnits);
	local capacity = FlieglTransportPackUtil.getCapacity(specFillUnit.fillUnits);
	local fillLevelPercent = math.floor((fillLevel / (capacity * multiplier)) * 100);

	if specExtendedManureSpreader.door.animations.left ~= "notDefined" then
		local playAnimationLeftButton = specExtendedManureSpreader.actionEvents[InputAction.OPEN_LEFT_DOOR_BUTTON];

		if playAnimationLeftButton ~= nil then
			local currentText = g_i18n:getText("CLOSE_LEFT_DOOR");

			g_inputBinding:setActionEventActive(playAnimationLeftButton.actionEventId, fillLevelPercent <= 50);
			g_inputBinding:setActionEventTextVisibility(playAnimationLeftButton.actionEventId, fillLevelPercent <= 50);

			if specExtendedManureSpreader.leftIsClosed then
				currentText = g_i18n:getText("OPEN_LEFT_DOOR");
			end;

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

	if specExtendedManureSpreader.door.animations.right ~= "notDefined" then
		local playAnimationRightButton = specExtendedManureSpreader.actionEvents[InputAction.OPEN_RIGHT_DOOR_BUTTON];

		if playAnimationRightButton ~= nil then
			local currentText = g_i18n:getText("CLOSE_RIGHT_DOOR");

			g_inputBinding:setActionEventActive(playAnimationRightButton.actionEventId, fillLevelPercent <= 50);
			g_inputBinding:setActionEventTextVisibility(playAnimationRightButton.actionEventId, fillLevelPercent <= 50);

			if specExtendedManureSpreader.rightIsClosed then
				currentText = g_i18n:getText("OPEN_RIGHT_DOOR");
			end;

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

function ExtendedManureSpreader:saveToXMLFile(xmlFile, key)
	local specExtendedManureSpreader = FlieglTransportPackUtil.getSpecByName(self, "extendedManureSpreader");
	
	setXMLBool(xmlFile, key .. "#leftIsClosed", specExtendedManureSpreader.leftIsClosed);
	setXMLBool(xmlFile, key .. "#rightIsClosed", specExtendedManureSpreader.rightIsClosed);
end;

SetLeftDoorStateEvent = {};
SetLeftDoorStateEvent_mt = Class(SetLeftDoorStateEvent, Event);

InitEventClass(SetLeftDoorStateEvent, "SetLeftDoorStateEvent");

function SetLeftDoorStateEvent:emptyNew()
	local self = Event:new(SetLeftDoorStateEvent_mt);
    
	return self;
end;

function SetLeftDoorStateEvent:new(manureSpreader, leftIsClosed)
	local self = SetLeftDoorStateEvent:emptyNew();
	
	self.manureSpreader = manureSpreader;
	self.leftIsClosed = leftIsClosed;
	
	return self;
end;

function SetLeftDoorStateEvent:readStream(streamId, connection)
	self.manureSpreader = NetworkUtil.readNodeObject(streamId);
	self.leftIsClosed = streamReadBool(streamId);
    
	self:run(connection);
end;

function SetLeftDoorStateEvent:writeStream(streamId, connection)
	NetworkUtil.writeNodeObject(streamId, self.manureSpreader);
	streamWriteBool(streamId, self.leftIsClosed);
end;

function SetLeftDoorStateEvent:run(connection)
	if not connection:getIsServer() then
		g_server:broadcastEvent(SetLeftDoorStateEvent:new(self.manureSpreader, self.leftIsClosed), nil, connection, self.manureSpreader);
	end;
	
    if self.manureSpreader ~= nil then
        self.manureSpreader:setLeftDoorState(self.leftIsClosed, true);
	end;
end;

function SetLeftDoorStateEvent.sendEvent(manureSpreader, leftIsClosed, noEventSend)
	if noEventSend == nil or noEventSend == false then
		if not noEventSend then
			if g_server ~= nil then
				g_server:broadcastEvent(SetRightDoorStateEvent:new(manureSpreader, leftIsClosed), nil, nil, manureSpreader);
			else
				g_client:getServerConnection():sendEvent(SetRightDoorStateEvent:new(manureSpreader, leftIsClosed));
			end;
		end;
	end;
end;

SetRightDoorStateEvent = {};
SetRightDoorStateEvent_mt = Class(SetRightDoorStateEvent, Event);

InitEventClass(SetRightDoorStateEvent, "SetRightDoorStateEvent");

function SetRightDoorStateEvent:emptyNew()
	local self = Event:new(SetLeftDoorStateEvent_mt);
    
	return self;
end;

function SetRightDoorStateEvent:new(manureSpreader, rightIsClosed)
	local self = SetRightDoorStateEvent:emptyNew();
	
	self.manureSpreader = manureSpreader;
	self.rightIsClosed = rightIsClosed;
	
	return self;
end;

function SetRightDoorStateEvent:readStream(streamId, connection)
	self.manureSpreader = NetworkUtil.readNodeObject(streamId);
	self.rightIsClosed = streamReadBool(streamId);
    
	self:run(connection);
end;

function SetRightDoorStateEvent:writeStream(streamId, connection)
	NetworkUtil.writeNodeObject(streamId, self.manureSpreader);
	streamWriteBool(streamId, self.rightIsClosed);
end;

function SetRightDoorStateEvent:run(connection)
	if not connection:getIsServer() then
		g_server:broadcastEvent(SetRightDoorStateEvent:new(self.manureSpreader, self.rightIsClosed), nil, connection, self.manureSpreader);
	end;
	
    if self.manureSpreader ~= nil then
        self.manureSpreader:setRightDoorState(self.rightIsClosed, true);
	end;
end;

function SetRightDoorStateEvent.sendEvent(manureSpreader, rightIsClosed, noEventSend)
	if noEventSend == nil or noEventSend == false then
		if not noEventSend then
			if g_server ~= nil then
				g_server:broadcastEvent(SetRightDoorStateEvent:new(manureSpreader, rightIsClosed), nil, nil, manureSpreader);
			else
				g_client:getServerConnection():sendEvent(SetRightDoorStateEvent:new(manureSpreader, rightIsClosed));
			end;
		end;
	end;
end;