--
-- Neptun Z-413
-- author: Burner
-- 

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

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

function Neptun:load(xmlFile)
    self.setIsTurnedOn = SpecializationUtil.callSpecializationsFunction("setIsTurnedOn");
	self.setTransport = SpecializationUtil.callSpecializationsFunction("setTransport");
	self.setLeafsDischarge = SpecializationUtil.callSpecializationsFunction("setLeafsDischarge");
	
	--self.drum = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.drum#index"));
	--self.pto = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.pto#index"));
	--self.cleaner = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.cleaner#index"));
	self.backMarker = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.backMarker#index"));
	
    self.animation = {};
    self.animation.animCharSet = 0;
    self.animationEnabled = false;
    local rootNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.animation#rootNode"));
    if rootNode ~= nil then
        self.animation.animCharSet = getAnimCharacterSet(rootNode);
        if self.animation.animCharSet ~= 0 then
            self.animation.clip = getAnimClipIndex(self.animation.animCharSet, getXMLString(xmlFile, "vehicle.animation#animationClip"));
            if self.animation.clip >= 0 then
                assignAnimTrackClip(self.animation.animCharSet, 0, self.animation.clip);
                self.animation.speedScale = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.animation#speedScale"), 1);
                setAnimTrackSpeedScale(self.animation.animCharSet, self.animation.clip, self.animation.speedScale);
                setAnimTrackLoopState(self.animation.animCharSet, 0, true);
            end;
        end;
    end;
	self.animationSpeed = 0;
	self.animation.offsetTime = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.animation#offsetTime"), 3) * 1000;
	
    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.NeptunGroundFlag = self:getNextDirtyFlag();
	
	self.transportAnimation = getXMLString(xmlFile, "vehicle.transport#animationName");
	self.transport = true;
	
	self.leafsDischargeAnimation = getXMLString(xmlFile, "vehicle.leafsDischarge#animationName");
	self.leafsDischarge = false;

	self.sugarbeetParticleSystem = {};
    local i = 0;
    while true do
        local namei = string.format("vehicle.sugarbeetParticleSystems.sugarbeetParticleSystem(%d)", i);
		local nodei = Utils.indexToObject(self.components, getXMLString(xmlFile, namei .. "#index"));
		if nodei == nil then
			break;
		end;
		StaticParticleSystem.loadParticleSystem(xmlFile, self.sugarbeetParticleSystem, namei, nodei, false, nil, self.baseDirectory);
		Utils.setEmittingState(self.sugarbeetParticleSystem,false);
		self.particleSystemdisableTime = 0;
		i = i +1;		
    end;
	self.leafsParticleSystem = {};
    local i = 0;
    while true do
        local namei = string.format("vehicle.leafsParticleSystems.leafsParticleSystem(%d)", i);
		local nodei = Utils.indexToObject(self.components, getXMLString(xmlFile, namei .. "#index"));
		if nodei == nil then
			break;
		end; 
		StaticParticleSystem.loadParticleSystem(xmlFile, self.leafsParticleSystem, namei, nodei, false, nil, self.baseDirectory);
		Utils.setEmittingState(self.leafsParticleSystem,false);
		self.particleSystemdisableTime = 0;
		i = i +1;		
    end;
	self.cleanerParticleSystem = {};
    local i = 0;
    while true do
        local namei = string.format("vehicle.cleanerParticleSystems.cleanerParticleSystem(%d)", i);
		local nodei = Utils.indexToObject(self.components, getXMLString(xmlFile, namei .. "#index"));
		if nodei == nil then
			break;
		end; 
		StaticParticleSystem.loadParticleSystem(xmlFile, self.cleanerParticleSystem, namei, nodei, false, nil, self.baseDirectory);
		Utils.setEmittingState(self.cleanerParticleSystem,false);
		self.particleSystemdisableTime = 0;
		i = i +1;		
    end;
	self.leafsDischargeParticleSystem = {};
    local i = 0;
    while true do
        local namei = string.format("vehicle.leafsDischargeParticleSystems.leafsDischargeParticleSystem(%d)", i);
		local nodei = Utils.indexToObject(self.components, getXMLString(xmlFile, namei .. "#index"));
		if nodei == nil then
			break;
		end; 
		StaticParticleSystem.loadParticleSystem(xmlFile, self.leafsDischargeParticleSystem, namei, nodei, false, nil, self.baseDirectory);
		Utils.setEmittingState(self.leafsDischargeParticleSystem,false);
		self.particleSystemdisableTime = 0;
		i = i +1;		
    end;
	
	self.leafsDischargeDuration = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.leafsDischargeParticleSystems#duration"), 1000);
	self.leafsDischargeEnableTime = nil;
	
	self.leafsTankCapacity = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.leafsTankCapacity"), 0.0);
	self.leafsFillLevel = 0;
	
	self.leafsFillLevelHUD = {};
	self.leafsFillLevelHUD.xPos = Utils.getNoNil(getXMLFloat(xmlFile,  "vehicle.leafsFillLevelHUD#posX"), 0.7543);
	self.leafsFillLevelHUD.yPos = Utils.getNoNil(getXMLFloat(xmlFile,  "vehicle.leafsFillLevelHUD#posY"), 0.8415);
	self.leafsFillLevelHUDOverlay = Overlay:new("leafsFillLevelHUDOverlay", Utils.getFilename("leafsFillLevelHUD.png", self.baseDirectory), self.leafsFillLevelHUD.xPos, self.leafsFillLevelHUD.yPos, 0.2371, 0.039525);
end;

function Neptun:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)
   local leafsFillLevel = Utils.getNoNil(getXMLInt(xmlFile, key.."#leafsFillLevel"),0);
   self.leafsFillLevel = leafsFillLevel;
   return BaseMission.VEHICLE_LOAD_OK;
end;

function Neptun:getSaveAttributesAndNodes(nodeIdent)
   local leafsFillLevel= Utils.getNoNil(self.leafsFillLevel, 0);
   local attributes = 'leafsFillLevel="'..string.format("%.1f",leafsFillLevel)..'"';
   return attributes, nil;
end;

function Neptun:delete()
end;

function Neptun:readStream(streamId, connection)
    local turnedOn = streamReadBool(streamId);
    self:setIsTurnedOn(turnedOn, true);
    local fillLevel = streamReadInt32(streamId);
	self:setTransport(streamReadBool(streamId), true);
	self:setLeafsDischarge(streamReadBool(streamId), true);
	self.lastAreaBiggerZero = streamReadBool(streamId);
	self.leafsFillLevel = streamReadInt32(streamId);
end;

function Neptun:writeStream(streamId, connection)
    streamWriteBool(streamId, self.isTurnedOn);
    streamWriteInt32(streamId, self.fillLevel);
	streamWriteBool(streamId, self.transport);
	streamWriteBool(streamId, self.leafsDischarge);
	streamWriteBool(streamId, self.lastAreaBiggerZero);
	streamWriteInt32(streamId, self.leafsFillLevel);
end;

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

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

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

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

function Neptun:update(dt)
    if self:getIsActiveForInput() then
        if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA) then
            self:setIsTurnedOn(not self.isTurnedOn);
        end;
		if InputBinding.hasEvent(InputBinding.Neptun_ToggleTransport) then
			self:setTransport(not self.transport);
		end;
		if InputBinding.hasEvent(InputBinding.ACTIVATE_THRESHING) then
			self:setLeafsDischarge(not self.leafsDischarge);
		end;
    end;
end;

function Neptun:updateTick(dt)
	if self.attacherVehicle ~= nil then
		for k, implement in pairs(self.attacherVehicle.attachedImplements) do
			local jointDesc = self.attacherVehicle.attacherJoints[implement.jointDescIndex];
			if k == self.attacherVehicle.selectedImplement  then
				setJointFrame(jointDesc.jointIndex, 1, self.attacherJoint.node);
			end;
		end;
	end;
	
    self.wasToFast = false;
    self.lastArea = 0;
    if self:getIsActive() then
		if self.isTurnedOn then
			rotate(self.backMarker, 2.5 * self.lastSpeedReal * self.movingDirection * dt ,0,0);
			--rotate(self.drum, dt*0.015, 0, 0 );
			--rotate(self.pto, 0, 0, 0.8);
			--rotate(self.cleaner, 0, 0.1, 0);
            if not self.animationEnabled then
                enableAnimTrack(self.animation.animCharSet, 0);
                self.animationEnabled = true;
			else
				if self.animationSpeed < (self.animation.speedScale - 0.01) then
					local newSpeed = Utils.getMovedLimitedValues({self.animationSpeed}, {self.animation.speedScale}, {0}, 1, self.animation.offsetTime, dt, false);
					self.animationSpeed = newSpeed[1];
					setAnimTrackSpeedScale(self.animation.animCharSet, 0, self.animationSpeed);
				end;
            end;

			if self.leafsFillLevel >= self.leafsTankCapacity then
				self:setLeafsDischarge(true);
			end;
			if self.leafsDischarge then
				self.leafsFillLevel = 0;
				if self.leafsDischargeEnableTime == nil then
					self.leafsDischargeEnableTime = self.time + self.leafsDischargeDuration;
				end;
				if self.leafsDischargeEnableTime ~= nil and self.leafsDischargeEnableTime <= self.time then
					self:setLeafsDischarge(false);
					self.leafsDischargeEnableTime = nil;
				end;
			end;
		else
			if self.animationEnabled then
				if self.animationSpeed < 0.01 then
					disableAnimTrack(self.animation.animCharSet, 0);
					self.animationEnabled = false;
				else
					enableAnimTrack(self.animation.animCharSet, 0);
					local newSpeed = Utils.getMovedLimitedValues({self.animationSpeed}, {self.animation.speedScale}, {0}, 1, self.animation.offsetTime, dt, true);
					self.animationSpeed = newSpeed[1];
					setAnimTrackSpeedScale(self.animation.animCharSet, 0, self.animationSpeed);
				end;
			end;
		end;
		Utils.setEmittingState(self.leafsDischargeParticleSystem, self.leafsDischarge);
        if self.isTurnedOn and self.capacity > self.fillLevel then
			Utils.setEmittingState(self.sugarbeetParticleSystem, self.lastAreaBiggerZero);
			Utils.setEmittingState(self.leafsParticleSystem, self.lastAreaBiggerZero);
			Utils.setEmittingState(self.cleanerParticleSystem, self.lastAreaBiggerZero);

            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 = NeptunAreaEvent.runLocally(cuttingAreasSend, self.fillTypes, self.currentFillType);
						self.lastArea = lastArea;
						self.lastAreaBiggerZero = (self.lastArea > 0);
                        if lastArea > 0 then
							self.currentFruitType = FruitUtil.fillTypeToFruitType[fillType];
                            self.lastNeptunArea = lastArea;
                            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;
                            self:setFillLevel(self.fillLevel+deltaLevel, fillType);
							self.leafsFillLevel = self.leafsFillLevel+deltaLevel;
							g_server:broadcastEvent(NeptunAreaEvent:new(cuttingAreasSend, fillType));
                        end;
                    end;
                end;
            end;
            self.wasToFast = toFast;
		else
			Utils.setEmittingState(self.sugarbeetParticleSystem, false);
			Utils.setEmittingState(self.leafsParticleSystem, false);
			Utils.setEmittingState(self.cleanerParticleSystem, false);
        end;
    end;
	self.percentageLeafsFillLevel = (self.leafsFillLevel/self.leafsTankCapacity)*100;
end;

function Neptun: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.IMPLEMENT_EXTRA);
    else
        g_currentMission:addHelpButtonText(string.format(g_i18n:getText("turn_on_OBJECT"), self.typeDesc), InputBinding.IMPLEMENT_EXTRA);
    end;
	if self.transport then
        g_currentMission:addHelpButtonText(string.format(g_i18n:getText("Neptun_TransportOff"), self.typeDesc), InputBinding.Neptun_ToggleTransport);
    else
		g_currentMission:addHelpButtonText(string.format(g_i18n:getText("Neptun_TransportOn"), self.typeDesc), InputBinding.Neptun_ToggleTransport);
    end;
	
	self.leafsFillLevelHUDOverlay:render();
	setTextBold(true);
	setTextAlignment(RenderText.ALIGN_LEFT);
	local percentage = tonumber(string.format("%d", self.percentageLeafsFillLevel));
	text = g_i18n:getText("Neptun_Leafs") .. ": " .. percentage .. "% ";
	renderText(self.leafsFillLevelHUD.xPos + 0.135, self.leafsFillLevelHUD.yPos + 0.0085, 0.02, text);	
end;

function Neptun:onDetach()
    if self.deactivateOnDetach then
        Neptun.onDeactivate(self);
    else
		Utils.setEmittingState(self.sugarbeetParticleSystem, false);
		Utils.setEmittingState(self.leafsParticleSystem, false);
		Utils.setEmittingState(self.cleanerParticleSystem, false);
		if self.animationEnabled then
			disableAnimTrack(self.animation.animCharSet, 0);
			self.animationEnabled = false;
		end;
    end;
end;

function Neptun:onLeave()
    if self.deactivateOnLeave then
        Neptun.onDeactivate(self);
    else
		Utils.setEmittingState(self.sugarbeetParticleSystem, false);
		Utils.setEmittingState(self.leafsParticleSystem, false);
		Utils.setEmittingState(self.cleanerParticleSystem, false);
		if self.animationEnabled then
			disableAnimTrack(self.animation.animCharSet, 0);
			self.animationEnabled = false;
		end;
    end;
end;

function Neptun:onDeactivate()
	Utils.setEmittingState(self.sugarbeetParticleSystem, false);
	Utils.setEmittingState(self.leafsParticleSystem, false);
	Utils.setEmittingState(self.cleanerParticleSystem, false);
    self.isTurnedOn = false;
    if self.animationEnabled then
        disableAnimTrack(self.animation.animCharSet, 0);
        self.animationEnabled = false;
    end;
end;

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

function Neptun:setTransport(isTransport,noEventSend)
	SetTransportEvent.sendEvent(self, isTransport, noEventSend);
	if isTransport then
		if self.transportAnimation ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.transportAnimation, -1, nil, true);
			self.transport = true;
		end;
	else
		if self.transportAnimation ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.transportAnimation, 1, nil, true);
			self.transport = false;
		end;
	end;
end;

function Neptun:setLeafsDischarge(isDischarge,noEventSend)
	SetLeafsDischargeEvent.sendEvent(self, isDischarge, noEventSend);
	if isDischarge then
		if self.leafsDischargeAnimation ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.leafsDischargeAnimation, 1, nil, true);
			self.leafsDischarge = true;
		end;
	else
		if self.leafsDischargeAnimation ~= nil and self.playAnimation ~= nil then
			self:playAnimation(self.leafsDischargeAnimation, -1, nil, true);
			self.leafsDischarge = false;
		end;
	end;
end;