--
-- Orkan Z302
-- author: Burner
-- 

source("dataS/scripts/vehicles/specializations/SetTurnedOnEvent.lua");
Orkan = {};

function Orkan.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(Trailer, specializations);
end;

function Orkan:load(xmlFile)
    self.setIsTurnedOn = SpecializationUtil.callSpecializationsFunction("setIsTurnedOn");
    self.fillScale = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.fillScale#value"), 1);
    self.wasToFast = false;
    self.isTurnedOn = false;
	self.currentFruitType = FruitUtil.FRUITTYPE_UNKNOWN;
	
	self.lastArea = 0;
	self.lastAreaBiggerZero = self.lastArea > 0;

	self.pto = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.pto#index"));

	self.pipeChaffParticleSystems = {};
    local i = 0;
    while true do
        local namei = string.format("vehicle.pipeChaffParticleSystems.pipeChaffParticleSystem(%d)", i);
		local nodei = Utils.indexToObject(self.components, getXMLString(xmlFile, namei .. "#index"));
		if nodei == nil then
			break;
		end; 
        Utils.loadParticleSystem(xmlFile, self.pipeChaffParticleSystems, namei, nodei, false, nil, self.baseDirectory)		
		Utils.setEmittingState(self.pipeChaffParticleSystems,false)
		i = i +1;		
    end;
	
	self.pipeStrawParticleSystems = {};
    local i = 0;
    while true do
        local namei = string.format("vehicle.pipeStrawParticleSystems.pipeStrawParticleSystem(%d)", i);
		local nodei = Utils.indexToObject(self.components, getXMLString(xmlFile, namei .. "#index"));
		if nodei == nil then
			break;
		end; 
        Utils.loadParticleSystem(xmlFile, self.pipeStrawParticleSystems, namei, nodei, false, nil, self.baseDirectory)		
		Utils.setEmittingState(self.pipeStrawParticleSystems,false)
		i = i +1;		
    end;
	
	self.currentPS = self.pipeChaffParticleSystems;

	self.trailerRaycastCallback = Orkan.trailerRaycastCallback;

	self.pipe = {};
	self.pipe.node = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.pipe#index"));
	self.pipe.distance = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.pipe#raycastDistance"), 7);

	self.isLoading = true;
end;

function Orkan:delete()
end;

function Orkan:readStream(streamId, connection)
    local turnedOn = streamReadBool(streamId);
    self:setIsTurnedOn(turnedOn, true);
	self.isLoading = true;
	self.lastAreaBiggerZero = streamReadBool(streamId);
	self.currentFruitType = streamReadInt8(streamId);
end;

function Orkan:writeStream(streamId, connection)
    streamWriteBool(streamId, self.isTurnedOn);
	streamWriteBool(streamId, self.lastAreaBiggerZero);
	streamWriteInt8(streamId, self.currentFruitType);
end;

function Orkan:readUpdateStream(streamId, timestamp, connection)
	if connection:getIsServer() then
		self.lastAreaBiggerZero = streamReadBool(streamId);
		self.currentFruitType = streamReadInt8(streamId);
	end;
end;

function Orkan:writeUpdateStream(streamId, connection, dirtyMask)
	if not connection:getIsServer() then
		streamWriteBool(streamId, self.lastAreaBiggerZero);
		streamWriteInt8(streamId, self.currentFruitType);
	end;
end;

function Orkan:mouseEvent(posX, posY, isDown, isUp, button)
end;

function Orkan:keyEvent(unicode, sym, modifier, isDown)
end;

function Orkan:update(dt)
    if self:getIsActiveForInput() then
        if InputBinding.hasEvent(InputBinding.Orkan_TurnOn) then
            self:setIsTurnedOn(not self.isTurnedOn);
        end;
		if InputBinding.isPressed(InputBinding.Orkan_PipeDown) and self:getIsActiveForInput() then
			self:setAnimationTime(1, self.animationParts[1].currentPosition+(self.animationParts[1].offSet+dt), false);
		elseif InputBinding.isPressed(InputBinding.Orkan_PipeUp) and self:getIsActiveForInput() then
			self:setAnimationTime(1, self.animationParts[1].currentPosition-(self.animationParts[1].offSet+dt), false);
		end;
    end;
end;

function Orkan:updateTick(dt)
	self.trailerFoundId = 0;
    self.wasToFast = false;
    self.lastArea = 0;
	
	local x, y, z = getWorldTranslation(self.pipe.node);
	local dx, dy, dz = localDirectionToWorld(self.pipe.node, 0, -0.5, 0);
	raycastAll(x, y, z, dx, dy, dz, "trailerRaycastCallback", self.pipe.distance, self);
			
    if self:getIsActive() then
		local deltaLevel = 0;
		if self.isTurnedOn then
			rotate(self.pto, 0, 0, 0.8);
		end;
        if self.isTurnedOn then
            local toFast = self:doCheckSpeedLimit() and self.attacherVehicle.lastSpeed*3600 > 29;
            if self.isServer then
                if not toFast then
                    local cuttingAreasSend = {};
                    for k, cuttingArea in pairs(self.cuttingAreas) do
                        if self:getIsAreaActive(cuttingArea) then
                            local x,y,z = getWorldTranslation(cuttingArea.start);
                            local x1,y1,z1 = getWorldTranslation(cuttingArea.width);
                            local x2,y2,z2 = getWorldTranslation(cuttingArea.height);
                            table.insert(cuttingAreasSend, {x,z,x1,z1,x2,z2});
                        end;
                    end;
                    if (table.getn(cuttingAreasSend) > 0) then
						local lastArea, fillType = OrkanAreaEvent.runLocally(cuttingAreasSend, self.fillTypes, self.currentFillType);
						self.lastArea = lastArea;
						self.lastAreaBiggerZero = (self.lastArea > 0);
                        if lastArea > 0 then
							self.currentFruitType = FruitUtil.fillTypeToFruitType[fillType];
							if self.currentFruitType == FruitUtil.FRUITTYPE_GRASS or self.currentFruitType == FruitUtil.FRUITTYPE_DRYGRASS or self.currentFruitType == FruitUtil.FRUITTYPE_MAIZE then 
								self.currentPS = self.pipeChaffParticleSystems
							else
								self.currentPS = self.pipeStrawParticleSystems;
							end;
                            local pixelToSqm = g_currentMission:getFruitPixelsToSqm(); -- 4096px are mapped to 2048m
							literPerSqm = FruitUtil.fruitIndexToDesc[self.currentFruitType].literPerSqm;
                            local sqm = lastArea *pixelToSqm;
                            local deltaLevel = sqm*literPerSqm * self.fillScale;
							
							if self.trailerFoundId ~= nil and self.trailerFoundId ~= 0 then
								local trailer = g_currentMission.nodeToVehicle[self.trailerFoundId];
								if trailer ~= nil and trailer ~= self and trailer:allowFillType(Fillable.FILLTYPE_CHAFF, true) and trailer.allowFillFromAir and trailer.capacity ~= trailer.fillLevel then
									trailer:setFillLevel(trailer.fillLevel+deltaLevel, Fillable.FILLTYPE_CHAFF);
								end;
							end;
							g_server:broadcastEvent(OrkanAreaEvent:new(cuttingAreasSend, fillType));
                        end;
                    end;
                end;
            end;
			Utils.setEmittingState(self.currentPS, self.lastAreaBiggerZero);
            self.wasToFast = toFast;
		else
			Utils.setEmittingState(self.pipeChaffParticleSystems, false);
			Utils.setEmittingState(self.pipeStrawParticleSystems, false);
        end;
    end;
end;

function Orkan:draw()
    if self.wasToFast then
        g_currentMission:addWarning(g_i18n:getText("Dont_drive_to_fast") .. "\n" .. string.format(g_i18n:getText("Cruise_control_levelN"), "2", InputBinding.getKeyNamesOfDigitalAction(InputBinding.SPEED_LEVEL2)), 0.07+0.022, 0.019+0.029);
    end;
    if self.isTurnedOn then
        g_currentMission:addHelpButtonText(string.format(g_i18n:getText("turn_off_OBJECT"), self.typeDesc), InputBinding.Orkan_TurnOn);
    else
        g_currentMission:addHelpButtonText(string.format(g_i18n:getText("turn_on_OBJECT"), self.typeDesc), InputBinding.Orkan_TurnOn);
    end;
	g_currentMission:addExtraPrintText(string.format(""..InputBinding.getKeyNamesOfDigitalAction(InputBinding.Orkan_PipeUp) .. " / " .. InputBinding.getKeyNamesOfDigitalAction(InputBinding.Orkan_PipeDown)..":                 "..g_i18n:getText("Orkan_Pipemove")..""));
end;

function Orkan:onDetach()
	Utils.setEmittingState(self.pipeChaffParticleSystems, false);
	Utils.setEmittingState(self.pipeStrawParticleSystems, false);
    if self.deactivateOnDetach then
        Orkan.onDeactivate(self);
    else
    end;
end;

function Orkan:onLeave()
	Utils.setEmittingState(self.pipeChaffParticleSystems, false);
	Utils.setEmittingState(self.pipeStrawParticleSystems, false);
    if self.deactivateOnLeave then
        Orkan.onDeactivate(self);
    else
    end;
end;

function Orkan:onDeactivate()
	Utils.setEmittingState(self.pipeChaffParticleSystems, false);
	Utils.setEmittingState(self.pipeStrawParticleSystems, false);
    self.isTurnedOn = false;
end;

function Orkan:setIsTurnedOn(turnedOn, noEventSend)
    SetTurnedOnEvent.sendEvent(self, turnedOn, noEventSend)
    self.isTurnedOn = turnedOn;
end;

function Orkan:trailerRaycastCallback(transformId, x, y, z, distance)
	local vehicle = g_currentMission.nodeToVehicle[transformId];
	if vehicle ~= nil then
		if vehicle.exactFillRootNode == transformId then
			self.trailerFoundId = transformId;
			return false;
		end;
	end;
	return true;
end;