FieldShuttle = {};

FieldShuttle.UNLOADING_CLOSED = 0;
FieldShuttle.UNLOADING_OPENING = 1;
FieldShuttle.UNLOADING_OPEN = 2;
FieldShuttle.UNLOADING_CLOSING = 3;

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

function FieldShuttle:load(xmlFile)
    self.findTrailerRaycastCallback = FieldShuttle.findTrailerRaycastCallback;
    self.trailerFound = 0;
    self.pipeParticleSystem = {};
    self.pipeParticleSystemindex = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.pipeParticleSystem#index"));
    Utils.loadParticleSystem(xmlFile, self.pipeParticleSystem, "vehicle.pipeParticleSystem", self.pipeParticleSystemindex, false, nil, self.baseDirectory);
	self.unloadingState = Trailer.UNLOADING_CLOSED;
	self.trailerPosition = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.trailerPosition#index"));
	self.grainUnloading = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.grainUnloading"), 10);
	self.isExpanded = false;
	self.pipeParticleActivated = false;
	self.isActive = false;
	self.trailertrigg = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.trailerPosition#index"));
	local balerAlarm = getXMLString(xmlFile, "vehicle.balerAlarm#file");
	if balerAlarm ~= nil and balerAlarm ~= "" then
		balerAlarm = Utils.getFilename(balerAlarm, self.baseDirectory);
		self.balerAlarm = createSample("balerAlarm");
		self.balerAlarmEnabled = false;
		loadSample(self.balerAlarm, balerAlarm, false);
		self.balerAlarmPitchOffset = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.balerAlarm#pitchOffset"), 1);
		self.balerAlarmVolume = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.balerAlarm#volume"), 1);
	end;
	self.w1 = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.w1#index"), 0);	
	self.w2 = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.w2#index"), 0);	
	self.w3 = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.w3#index"), 0);	
	self.w4 = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.w4#index"), 0);	
    self.autoBeacon=false;
	self.activeopen=false;
	self.bunkerrechts=true;
	self.waitForDischargeTimeout = 5000;
	self.waitForDischargeTime = 0;
	self.haeckseldolly = true;
end;

function FieldShuttle:delete()
	if self.hudHaweOverlay ~= nil then
		self.hudHaweOverlay:delete();
	end;
	if self.balerAlarm ~= nil then
          delete(self.balerAlarm);
          self.balerAlarmEnabled = false;
     end;
	 if self.pipeParticleSystem ~= nil then
		Utils.deleteParticleSystem(self.pipeParticleSystem);
	end
	if self.hydraulicSound ~= nil then 
	 delete(self.hydraulicSound)
	end
end;

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

function FieldShuttle:keyEvent(unicode, sym, modifier, isDown)
end;
function FieldShuttle:readStream(streamId, connection)
	self.bunkerrechts = streamReadBool(streamId);
end;

function FieldShuttle:writeStream(streamId, connection)
	streamWriteBool(streamId, self.bunkerrechts);
end;
function FieldShuttle:update(dt)
local bunkerr = self.bunkerrechts;
  if self.isClient and self:getIsActiveForInput(false) and not self:hasInputConflictWithSelection() then
		if InputBinding.hasEvent(InputBinding.BUNKER_updown) then
			if self.unloadingState == FieldShuttle.UNLOADING_OPEN then
				self:setAnimationTime(1, self.animationParts[1].offSet, false);
			else
				self:setAnimationTime(1, self.animationParts[1].animDuration, false);
			end;
		end;
		if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA2) then
			if self.unloadingState == FieldShuttle.UNLOADING_OPEN then
				if self.bunkerrechts then
					self.bunkerrechts=false;
				else
					self.bunkerrechts=true;
				end;
			end;
		end;
end
	if self.animationParts[1].inputDone and self.animationParts[1].clipEndTime then
		self.unloadingState = FieldShuttle.UNLOADING_OPEN
	elseif not self.animationParts[1].clipEndTime then
		self.unloadingState = FieldShuttle.UNLOADING_CLOSED
		self:setAnimationTime(3, self.animationParts[3].startPosition, false);
	end;
	if self.unloadingState == FieldShuttle.UNLOADING_OPEN then
		if self.bunkerrechts then
			self:setAnimationTime(3, self.animationParts[3].offSet, false);
			if self.animationParts[3].currentPosition <= 1500 then
				setVisibility(self.w1, true);
				setVisibility(self.w2, false);
				setVisibility(self.w3, true);
				setVisibility(self.w4, false);
			end;
		else
			self:setAnimationTime(3, self.animationParts[3].animDuration, false);
			if self.animationParts[3].currentPosition >= 8500 then
				setVisibility(self.w1, false);
				setVisibility(self.w2, true);
				setVisibility(self.w3, false);
				setVisibility(self.w4, true);
			end;			
		end;
	end;
	local hydraulicSoundEnabled = false;
	for i=1, 1 do
		if not self.animationParts[i].inputDone then
			hydraulicSoundEnabled = true;
		end;
	end;
	if hydraulicSoundEnabled then
		if not self.hydraulicSoundEnabled and self.hydraulicSound ~= nil and self:getIsActiveForSound() then
			playSample(self.hydraulicSound, 0, self.hydraulicSoundVolume, 0);
			setSamplePitch(self.hydraulicSound, self.hydraulicSoundPitchOffset-0.4);
			self.hydraulicSoundEnabled = true;   
		end;
	else
		if self.hydraulicSoundEnabled then
			stopSample(self.hydraulicSound);
			self.hydraulicSoundEnabled = false;   
		end;
	end;
	self.pipeParticleActivated = false;
	self.activeUnloading = true;
	self.trailerFound = 0;
    if self.unloadingState == FieldShuttle.UNLOADING_OPEN and self.fillLevel > 0 and self.attacherVehicle ~= nil then
        self.pipeParticleActivated = true;
        self.trailerFound = 0;
        local x,y,z = getWorldTranslation(self.trailerPosition);
        raycastAll(x, y, z, 0, -1, 0, "findTrailerRaycastCallback", 14, self);
		local trailer = g_currentMission.objectToTrailer[self.trailerFound];
		if (self.trailerFound == 0 or not trailer:allowFillType(self.currentFillType)) then
			self.pipeParticleActivated = false;
			self.activeUnloading = false;
			if self.activeopen then
				self:setAnimationTime(2, self.animationParts[2].offSet, false);
			end
		else
			if self.activeUnloading then
				local deltaLevel = self.grainUnloading;
				if trailer ~= nil then
					deltaLevel = math.min(deltaLevel, trailer.capacity - trailer.fillLevel);
				else
					deltaLevel = 0;
				end;
				if deltaLevel == 0 then
					self.pipeParticleActivated = false;
					self:setAnimationTime(2, self.animationParts[2].offSet, false);
				else
					if not self.activeopen then
						self:setAnimationTime(2, self.animationParts[2].animDuration, false);
					end;
					if self.animationParts[2].inputDone and self.animationParts[2].clipEndTime then
						self.fillLevel = self.fillLevel-deltaLevel;
						if self.fillLevel <= 0.0 then
							deltaLevel = deltaLevel+self.fillLevel;
							self.fillLevel = 0.0;
							self.pipeParticleActivated = false;
							self:setAnimationTime(2, self.animationParts[2].offSet, false);
						end;
						self:setFillLevel(self.fillLevel, self.currentFillType);
						if trailer ~= nil then
							trailer:setFillLevel(trailer.fillLevel+deltaLevel, self.currentFillType);
						end;
					elseif not self.animationParts[2].clipEndTime then
						self.activeopen = false;
					end;
				end;
			else
				self.pipeParticleActivated = false;
				self:setAnimationTime(2, self.animationParts[2].offSet, false);
			end;
		end;
	else
		self.activeUnloading = false;	
	end;
	self.activeopen = self.animationParts[2].inputDone and self.animationParts[2].clipEndTime;
	if self.activeopen and self.activeUnloading and self.pipeParticleActivated then
		Utils.setEmittingState(self.pipeParticleSystem, true);
	else
		Utils.setEmittingState(self.pipeParticleSystem, false);
	end;
	if self.attacherVehicle then
		self.attacherVehicle.numAttachedTrailers = 0;	
		if self.attacherVehicle.isAIThreshing then
			self.attacherVehicle.haeckseldolly = true;
			if (self.fillLevel > 0 or self.capacity <= 0) and (self.fillLevel >= self.capacity*0.8 or self.activeopen) then
				if self.activeopen then
					self.waitForDischargeTime = self.time + self.waitForDischargeTimeout;
				end;
				if self.fillLevel >= self.capacity and self.capacity > 0 then
					self.attacherVehicle.waitingForDischarge = true;
					self.waitForDischargeTime = self.time + self.waitForDischargeTimeout;
				end;
			else
				if (self.attacherVehicle.waitingForDischarge and self.fillLevel <= 0) or self.waitForDischargeTime <= self.time then
					self.attacherVehicle.waitingForDischarge = false;
					if self.attacherVehicle:getIsThreshingAllowed(true) then
						self.attacherVehicle:setIsThreshing(true);
					end;
				end;
			end;
			if self.attacherVehicle.turnStage == 2 then
				self.attacherVehicle.turnStage = 3;
				self.bunkerrechts = not self.bunkerrechts;
				for cutter,implement in pairs(self.attacherVehicle.attachedCutters) do
					local jointDesc = self.attacherVehicle.attacherJoints[implement.jointDescIndex];
					jointDesc.moveDown = true;
				end;
				self.attacherVehicle.allowsThreshing = true;
				self.attacherVehicle.aiRescueTimer = self.aiRescueTimeout;
			end;
		end;
		if (self.fillLevel >= self.capacity*0.93) and not self.autoBeacon then
          self.attacherVehicle:setBeaconLightsVisibility(true);
          self.autoBeacon=true;
        end;                                    
        if (self.fillLevel < self.capacity*0.93) and self.autoBeacon then
			self.attacherVehicle:setBeaconLightsVisibility(false);
			self.autoBeacon = false;
        end; 		
		if self.fillLevel > (self.capacity * 0.93) and self.fillLevel < self.capacity then
			if not self.balerAlarmEnabled and self:getIsActiveForSound() then
				setSamplePitch(self.balerAlarm, self.balerAlarmPitchOffset);
				playSample(self.balerAlarm, 0, self.balerAlarmVolume, 0);
				self.balerAlarmEnabled = true;
			end;
		else
			if self.balerAlarmEnabled then
				stopSample(self.balerAlarm);
				self.balerAlarmEnabled = false;
			end;
		end;
	end;
	if bunkerr ~= self.bunkerrechts then
		FieldShuttleEvent.sendEvent(self, self.bunkerrechts);
	end;
end;

function FieldShuttle:draw()
	if self.attacherVehicle ~= nil then
		if self.unloadingState == FieldShuttle.UNLOADING_OPEN then
			g_currentMission:addExtraPrintText("Taste M: Bunker senken");
			if self.bunkerrechts then
				g_currentMission:addExtraPrintText("Taste X: Bunker nach links drehn");
			else
				g_currentMission:addExtraPrintText("Taste X: Bunker nach rechts drehn");
			end
		else
			g_currentMission:addExtraPrintText("Taste M: Bunker heben");
		end;
	end;
end;

function FieldShuttle:onDetach()
	self.oldvehicle.haeckseldolly = false;
end;
function FieldShuttle:onAttach(attacherVehicle)
	self.oldvehicle = attacherVehicle;
	attacherVehicle.haeckseldolly = true;
end;
function FieldShuttle:setFillLevel(fillLevel, fillType)
	Trailer.setFillLevel(self, fillLevel, fillType);
    if self.windowGrainPlane ~= nil then
        local yTranslation;
        if self.windowGrainAnimCurve then
            local scaleX, scaleY, scaleZ , yTrans = self.windowGrainAnimCurve:get(self.fillLevel/self.capacity);
            yTranslation = yTrans;
            setScale(self.windowGrainPlane, scaleX, scaleY, scaleZ);
        else
            local m = (self.windowGrainPlaneMaxY - self.windowGrainPlaneMinY) / self.capacity;
            yTranslation = m*self.fillLevel + self.windowGrainPlaneMinY;
        end;
            local xPos, yPos, zPos = getTranslation(self.windowGrainPlane);
        setTranslation(self.windowGrainPlane, xPos, yTranslation, zPos);
        setVisibility(self.windowGrainPlane, self.fillLevel ~= 0);
    end;

end;

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


FieldShuttleEvent = {};
FieldShuttleEvent_mt = Class(FieldShuttleEvent, Event);

InitEventClass(FieldShuttleEvent, "FieldShuttleEvent");

function FieldShuttleEvent:emptyNew()
    local self = Event:new(FieldShuttleEvent_mt);
    self.className="FieldShuttleEvent";
    return self;
end;

function FieldShuttleEvent:new(object, data)
    local self = FieldShuttleEvent:emptyNew()
    self.object = object;
	self.data = data;
    return self;
end;

function FieldShuttleEvent:readStream(streamId, connection)
    local id = streamReadInt32(streamId);
	self.object = networkGetObject(id);
	self.data = streamReadBool(streamId);
	self.object.bunkerrechts = self.data;
	if not connection:getIsServer() then
        g_server:broadcastEvent(FieldShuttleEvent:new(self.object, self.data), nil, connection, self.object);
    end;
end;

function FieldShuttleEvent:writeStream(streamId, connection)
    streamWriteInt32(streamId, networkGetObjectId(self.object));
	streamWriteBool(streamId, self.data);
end;

function FieldShuttleEvent.sendEvent(vehicle, data)
	if g_server ~= nil then
		g_server:broadcastEvent(FieldShuttleEvent:new(vehicle, data), nil, nil, vehicle);
	else
		g_client:getServerConnection():sendEvent(FieldShuttleEvent:new(vehicle, data));
	end;
end;
