Gripper = {};


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

function Gripper:load(xmlFile)

    self.findTrailerRaycastCallback = Gripper.findTrailerRaycastCallback;
	self.findManureTriggerRaycastCallback = Gripper.findManureTriggerRaycastCallback;
    self.setManureFillLevel = Gripper.setManureFillLevel;

	self.manureRaycastNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.gripper#raycastNode"));
	self.fillLevel = 0;
	self.capacity = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.gripper#capacity"), 0);
	
	self.manurePlane = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.manurePlane#index"));
	if self.manurePlane ~= nil then
		local manurePlanAnimCurve = AnimCurve:new(linearInterpolator3);
        local keyI = 0;
        while true do
            local key = string.format("vehicle.manurePlane.key(%d)", keyI);
            local t = getXMLFloat(xmlFile, key.."#time");
            local scaleX, scaleY, scaleZ = Utils.getVectorFromString(getXMLString(xmlFile, key.."#scale"));
            if scaleX == nil or scaleY == nil or scaleZ == nil then
                break;
            end;
            manurePlanAnimCurve:addKeyframe({x=scaleX, y=scaleY, z=scaleZ, time = t});
            keyI = keyI +1;
        end;
        if keyI > 0 then
            self.manurePlanAnimCurve = manurePlanAnimCurve;
        end;
	end;
 
    self.emptyParticleSystems = {};
    Utils.loadParticleSystem(xmlFile, self.emptyParticleSystems, "vehicle.emptyParticleSystem", self.components, false, nil, self.baseDirectory);

    self:setManureFillLevel(self.fillLevel);
end;

function Gripper:delete()
	Utils.deleteParticleSystem(self.emptyParticleSystems);
end;

function Gripper:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)
    local manureFillLevel = getXMLFloat(xmlFile, key.."#manureFillLevel");
    if manureFillLevel ~= nil then
        self:setManureFillLevel(manureFillLevel);
    end;
    return BaseMission.VEHICLE_LOAD_OK;
end;

function Gripper:getSaveAttributesAndNodes(nodeIdent)
	local attributes = 'manureFillLevel="'..tostring(self.fillLevel)..'"';
	return attributes, nil;
end;

function Gripper:readStream(streamId, connection)
	local fillLevel = streamReadFloat32(streamId);
	self:setManureFillLevel(fillLevel);
end;

function Gripper:writeStream(streamId, connection)
	streamWriteFloat32(streamId, self.fillLevel);
end;

function Gripper:readUpdateStream(streamId, timestamp, connection)
    if connection:getIsServer() then
        local fillLevel = streamReadFloat32(streamId);
        self:setManureFillLevel(fillLevel);
    end;
end;

function Gripper:writeUpdateStream(streamId, connection, dirtyMask)
    if not connection:getIsServer() then
        streamWriteFloat32(streamId, self.fillLevel);
    end;
end;

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

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

function Gripper:update(dt)

	local emptyingTime = self.animationParts[6].animDuration/10;
	self.triggerFound = 0;
	local x, y, z = getWorldTranslation(self.manureRaycastNode);
	local dx, dy, dz = localDirectionToWorld(self.manureRaycastNode, 0, -1, 0);
	raycastAll(x, y, z, dx, dy, dz, "findManureTriggerRaycastCallback", 1.7, self);
	if self.isServer then
		if self.fillLevel < self.capacity then
			if self.triggerFound ~= 0 and g_currentMission.missionStats.farmSiloAmounts[Fillable.FILLTYPE_MANURE] > 0 then
				local fillLevel = (self.capacity/self.animationParts[6].animDuration)*self.animationParts[6].currentPosition;
				if self.fillLevel < fillLevel then
					self:setManureFillLevel(self.fillLevel+fillLevel);
				end;	
			end;
		end;
	end;
	self.trailerFound = 0;
	if self.manureRaycastNode ~= nil then
		local x,y,z = getWorldTranslation(self.manureRaycastNode);
		local dx, dy, dz = localDirectionToWorld(self.manureRaycastNode, 0, -1, 0);
		raycastAll(x, y, z, dx, dy, dz, "findTrailerRaycastCallback", 10, self);
		local trailer = g_currentMission.objectToTrailer[self.trailerFound];
		if self.isServer then
			if self.fillLevel > 0 then
				local fillDelta = 0;
				if self.animationParts[6].currentPosition > emptyingTime and self.triggerFound == 0 then
					fillDelta = ((self.capacity/(self.animationParts[6].animDuration-emptyingTime))*self.animationParts[6].currentPosition)/10;
				end;
				g_currentMission.missionStats.farmSiloAmounts[Fillable.FILLTYPE_MANURE] = g_currentMission.missionStats.farmSiloAmounts[Fillable.FILLTYPE_MANURE] - fillDelta;
				if g_currentMission.missionStats.farmSiloAmounts[Fillable.FILLTYPE_MANURE] < 0 then
					g_currentMission.missionStats.farmSiloAmounts[Fillable.FILLTYPE_MANURE] = 0;
				end;
				if self.trailerFound ~= 0 and trailer ~= nil then
					if trailer:allowFillType(Fillable.FILLTYPE_MANURE) and trailer.allowFillFromAir then
						trailer:resetFillLevelIfNeeded(Fillable.FILLTYPE_MANURE);
						trailer:setFillLevel(trailer.fillLevel + fillDelta, Fillable.FILLTYPE_MANURE);
					end;
				end;
				self:setManureFillLevel(self.fillLevel-fillDelta);
			end;
		end;
		if self.trailerFound ~= 0 and trailer ~= nil and g_gui.currentGui == nil then
			local percent = (100/trailer.capacity)*trailer.fillLevel;
			local text = string.format("%d (%d%%)", trailer.fillLevel, percent);
			local x, y, z = getWorldTranslation(trailer.exactFillRootNode);
			local x1,y1,z1 = getWorldTranslation(getCamera())
			local distSq = Utils.vector3LengthSq(x-x1,y-y1,z-z1);
			if distSq <= 200 then
				y = y + 4;
				local sx, sy, sz = project(x, y, z);
				if sz <= 1 then
					setTextAlignment(RenderText.ALIGN_CENTER);
					setTextBold(false);		
					setTextColor(0.5, 1.0, 0.5, 1.0);                      
					renderText(sx, sy, 0.035, text);	
					setTextAlignment(RenderText.ALIGN_LEFT);
				end;
			end;
		end;
	end;
end;

function Gripper:updateTick(dt)
end;

function Gripper:draw()
end;

function Gripper:onDetach()
    if self.deactivateOnDetach then
        Gripper.onDeactivate(self);
    else
        Gripper.onDeactivateSounds(self);
    end;
end;

function Gripper:onLeave()
    if self.deactivateOnLeave then
        Gripper.onDeactivate(self);
    else
        Gripper.onDeactivateSounds(self);
    end;
end;

function Gripper:onDeactivate()
	Gripper.onDeactivateSounds(self);
end;

function Gripper:onDeactivateSounds()
end;

function Gripper:setManureFillLevel(fillLevel)
	local lastFillLevel = self.fillLevel;
	self.fillLevel = math.max(math.min(fillLevel, self.capacity), 0);
	if (self.fillLevel < lastFillLevel) and self.triggerFound == 0 then
		Utils.resetNumOfEmittedParticles(self.emptyParticleSystems);
		Utils.setEmittingState(self.emptyParticleSystems, true);
	end;
    if self.manurePlane ~= nil and self.manurePlanAnimCurve ~= nil then
		local t = self.fillLevel/self.capacity;
		local scaleX, scaleY, scaleZ = self.manurePlanAnimCurve:get(t);
        setScale(self.manurePlane, scaleX, scaleY, scaleZ);
        setVisibility(self.manurePlane, self.fillLevel > 0);
    end;
end;

function Gripper:getIsManureEmptying()
    return false;
end;

function Gripper:findTrailerRaycastCallback(transformId, x, y, z, distance)
    if getUserAttribute(transformId, "vehicleType") == 2 then
        self.trailerFound = transformId;
        return false;
    end;
    return true;
end;

function Gripper:findManureTriggerRaycastCallback(transformId, x, y, z, distance)
	local id = 0;
    if getCollisionMask(transformId) == 8192 then
        id = transformId;
    end;
	self.triggerFound = id;
	return;
end;

