AICombineDolly = {}

function AICombineDolly.prerequisitesPresent(specializations)
	return SpecializationUtil.hasSpecialization(AICombine, specializations)
end

function AICombineDolly:load(xmlFile)
	self.haeckseldolly = false;
	self.TargetXb = 0;
	self.TargetZb = 0;
end

function AICombineDolly:delete()
end;

function AICombineDolly:readStream(streamId, connection)
end;

function AICombineDolly:writeStream(streamId, connection)
end;

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

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

function AICombineDolly:update(dt)
end

function AICombineDolly:updateAIMovement( superFunc, dt )
	if not self:getIsAIThreshingAllowed() then
		self:stopAIThreshing()
		return
	end
	if not self.isControlled then
		if g_currentMission.environment.needsLights then
			self:setLightsVisibility(true)
		else
			self:setLightsVisibility(false)
		end
	end
	local allowedToDrive = true
	if self.grainTankCapacity == 0 then
		if not self.pipeStateIsUnloading[self.currentPipeState] then
			allowedToDrive = false
		end
		if not self.isPipeUnloading and (0 < self.lastArea or 0 < self.lastLostGrainTankFillLevel) then
			self.waitingForTrailerToUnload = true
		end
	elseif self.grainTankFillLevel >= self.grainTankCapacity then
		allowedToDrive = false
	end
	if self.waitingForTrailerToUnload then
		if self.lastValidGrainTankFruitType ~= FruitUtil.FRUITTYPE_UNKNOWN then
			do
				local trailer = self:findTrailerToUnload(self.lastValidGrainTankFruitType)
				if trailer ~= nil then
					self.waitingForTrailerToUnload = false
				end
			end
		else
			self.waitingForTrailerToUnload = false
		end
	end
	if self.grainTankFillLevel >= self.grainTankCapacity and self.grainTankCapacity > 0 or self.waitingForTrailerToUnload or self.waitingForDischarge then
		allowedToDrive = false
	end
	for _, v in pairs(self.numCollidingVehicles) do
		if v > 0 then
			allowedToDrive = false
			break
		end
	end
	if 0 < self.turnStage and (self.waitForTurnTime > self.time or self.pipeIsUnloading and self.turnStage < 3) then
		allowedToDrive = false
	end
	if not self:getIsThreshingAllowed(true) then
		allowedToDrive = false
		self:setIsThreshing(false)
		self.waitingForWeather = true
	elseif self.waitingForWeather then
		if self.turnStage == 0 then
			self.driveBackTime = self.time + self.driveBackTimeout
		end
		self:startThreshing()
		self.waitingForWeather = false
	end
	if not allowedToDrive then
		AIVehicleUtil.driveInDirection(self, dt, 30, 0, 0, 28, false, moveForwards, nil, nil)
		return
	end
	local speedLevel = 2
	local leftMarker = self.aiLeftMarker
	local rightMarker = self.aiRightMarker
	local hasFruitPreparer = false
	local fruitType = self.lastValidInputFruitType
	if self.fruitPreparerFruitType ~= nil and self.fruitPreparerFruitType == fruitType then
		hasFruitPreparer = true
	end
	for cutter, implement in pairs(self.attachedCutters) do
		if cutter.aiLeftMarker ~= nil and leftMarker == nil then
			leftMarker = cutter.aiLeftMarker
		end
		if cutter.aiRightMarker ~= nil and rightMarker == nil then
			rightMarker = cutter.aiRightMarker
		end
		if Cutter.getUseLowSpeedLimit(cutter) then
			speedLevel = 1
		end
	end
	if leftMarker == nil or rightMarker == nil then
		self:stopAIThreshing()
		return
	end
	if self.driveBackTime >= self.time then
		local x, y, z = getWorldTranslation(self.aiTreshingDirectionNode)
		local lx, lz = AIVehicleUtil.getDriveDirection(self.aiTreshingDirectionNode, self.aiThreshingTargetX, y, self.aiThreshingTargetZ)
		AIVehicleUtil.driveInDirection(self, dt, 30, 0, 0, 28, true, false, lx, lz, speedLevel, 1)
		return
	end
	local hasArea = true
	if self.lastArea < 1 then
		local x, y, z = getWorldTranslation(self.aiTreshingDirectionNode)
		local dirX, dirZ = self.aiThreshingDirectionX, self.aiThreshingDirectionZ
		local lInX, lInY, lInZ = getWorldTranslation(leftMarker)
		local rInX, rInY, rInZ = getWorldTranslation(rightMarker)
		local heightX = lInX + dirX * self.frontAreaSize
		local heightZ = lInZ + dirZ * self.frontAreaSize
		local area = Utils.getFruitArea(fruitType, lInX, lInZ, rInX, rInZ, heightX, heightZ, hasFruitPreparer)
		if area < 1 then
			hasArea = false
		end
	end
	if hasArea then
		self.turnTimer = self.turnTimeout
	else
		self.turnTimer = self.turnTimer - dt
	end
	local newTargetX, newTargetY, newTargetZ
	local moveForwards = true
	local updateWheels = true
	if 0 > self.turnTimer or 0 < self.turnStage then
		if 0 < self.turnStage then
			do
				local x, y, z = getWorldTranslation(self.aiTreshingDirectionNode)
				local dirX, dirZ = self.aiThreshingDirectionX, self.aiThreshingDirectionZ
				local myDirX, myDirY, myDirZ = localDirectionToWorld(self.aiTreshingDirectionNode, 0, 0, 1)
				newTargetX = self.aiThreshingTargetX
				newTargetY = y
				newTargetZ = self.aiThreshingTargetZ
				if self.turnStage == 1 then
					self.turnStageTimer = self.turnStageTimer - dt
					if self.lastSpeed < self.aiRescueSpeedThreshold then
						self.aiRescueTimer = self.aiRescueTimer - dt
					else
						self.aiRescueTimer = self.aiRescueTimeout
					end
					if myDirX * dirX + myDirZ * dirZ > self.turnStage1AngleCosThreshold or 0 > self.turnStageTimer or 0 > self.aiRescueTimer then
						self.turnStage = 2
						moveForwards = false
						if 0 > self.turnStageTimer or 0 > self.aiRescueTimer then
							self.aiThreshingTargetBeforeSaveX = self.aiThreshingTargetX
							self.aiThreshingTargetBeforeSaveZ = self.aiThreshingTargetZ
							newTargetX = self.aiThreshingTargetBeforeTurnX
							newTargetZ = self.aiThreshingTargetBeforeTurnZ
							moveForwards = false
							self.turnStage = 4
							self.turnStageTimer = self.turnStage4Timeout
						else
							self.turnStageTimer = self.turnStage2Timeout
						end
						self.aiRescueTimer = self.aiRescueTimeout
					end
				elseif self.turnStage == 2 then
					self.turnStageTimer = self.turnStageTimer - dt
					if self.lastSpeed < self.aiRescueSpeedThreshold then
						self.aiRescueTimer = self.aiRescueTimer - dt
					else
						self.aiRescueTimer = self.aiRescueTimeout
					end
					if myDirX * dirX + myDirZ * dirZ > self.turnStage2AngleCosThreshold or 0 > self.turnStageTimer or 0 > self.aiRescueTimer then
						AICombine.switchToTurnStage3(self)
					else
						moveForwards = false
					end
				elseif self.turnStage == 3 then
					if self.lastSpeed < self.aiRescueSpeedThreshold then
						self.aiRescueTimer = self.aiRescueTimer - dt
					else
						self.aiRescueTimer = self.aiRescueTimeout
					end
					do
						local dx, dz = x - newTargetX, z - newTargetZ
						local dot = dx * dirX + dz * dirZ
						if -dot < self.turnEndDistance then
							self.turnTimer = self.turnTimeoutLong
							self.turnStage = 0
						elseif 0 > self.aiRescueTimer then
							self.aiThreshingTargetBeforeSaveX = self.aiThreshingTargetX
							self.aiThreshingTargetBeforeSaveZ = self.aiThreshingTargetZ
							newTargetX = self.aiThreshingTargetBeforeTurnX
							newTargetZ = self.aiThreshingTargetBeforeTurnZ
							moveForwards = false
							self.turnStage = 4
							self.turnStageTimer = self.turnStage4Timeout
						end
					end
				elseif self.turnStage == 4 then
					self.turnStageTimer = self.turnStageTimer - dt
					if self.lastSpeed < self.aiRescueSpeedThreshold then
						self.aiRescueTimer = self.aiRescueTimer - dt
					else
						self.aiRescueTimer = self.aiRescueTimeout
					end
					if 0 > self.aiRescueTimer then
						self.aiRescueTimer = self.aiRescueTimeout
						local x, y, z = localDirectionToWorld(self.aiRescueNode, 0, 0, -1)
						local scale = self.aiRescueForce / Utils.vector2Length(x, z)
						addForce(self.aiRescueNode, x * scale, 0, z * scale, 0, 0, 0, true)
					end
					if 0 > self.turnStageTimer then
						self.aiRescueTimer = self.aiRescueTimeout
						self.turnStageTimer = self.turnStage1Timeout
						self.turnStage = 1
						newTargetX = self.aiThreshingTargetBeforeSaveX
						newTargetZ = self.aiThreshingTargetBeforeSaveZ
					else
						local dirX, dirZ = -dirX, -dirZ
						local targetX, targetZ = self.aiThreshingTargetX, self.aiThreshingTargetZ
						local dx, dz = x - targetX, z - targetZ
						local dot = dx * dirX + dz * dirZ
						local projTargetX = targetX + dirX * dot
						local projTargetZ = targetZ + dirZ * dot
						newTargetX = projTargetX - dirX * self.lookAheadDistance
						newTargetZ = projTargetZ - dirZ * self.lookAheadDistance
						moveForwards = false
					end
				elseif self.turnStage == 5 then
					self.turnStageTimer = self.turnStageTimer - dt;
					if self.lastSpeed < self.aiRescueSpeedThreshold then
						self.aiRescueTimer = self.aiRescueTimer - dt;
					else
						self.aiRescueTimer = self.aiRescueTimeout;
					end;
					if myDirX*dirX + myDirZ*dirZ > -0.90 or self.turnStageTimer < 0 or self.aiRescueTimer < 0 then
						newTargetX = self.TargetXb;
						newTargetZ = self.TargetZb;
						self.turnStage = 1;
					end;
					self.aiRescueTimer = self.aiRescueTimeout;
				end;
			end;
		elseif fruitType == FruitUtil.FRUITTYPE_UNKNOWN then
			self:stopAIThreshing()
			return
		else
			local x, y, z = getWorldTranslation(self.aiTreshingDirectionNode)
			local dirX, dirZ = self.aiThreshingDirectionX, self.aiThreshingDirectionZ
			local sideX, sideZ = -dirZ, dirX
			local lInX, lInY, lInZ = getWorldTranslation(leftMarker)
			local rInX, rInY, rInZ = getWorldTranslation(rightMarker)
			local threshWidth = Utils.vector2Length(lInX - rInX, lInZ - rInZ)
			local turnLeft = true
			local lWidthX = x - sideX * 0.5 * threshWidth + dirX * self.sideWatchDirOffset
			local lWidthZ = z - sideZ * 0.5 * threshWidth + dirZ * self.sideWatchDirOffset
			local lStartX = lWidthX - sideX * 0.7 * threshWidth
			local lStartZ = lWidthZ - sideZ * 0.7 * threshWidth
			local lHeightX = lStartX + dirX * self.sideWatchDirSize
			local lHeightZ = lStartZ + dirZ * self.sideWatchDirSize
			local rWidthX = x + sideX * 0.5 * threshWidth + dirX * self.sideWatchDirOffset
			local rWidthZ = z + sideZ * 0.5 * threshWidth + dirZ * self.sideWatchDirOffset
			local rStartX = rWidthX + sideX * 0.7 * threshWidth
			local rStartZ = rWidthZ + sideZ * 0.7 * threshWidth
			local rHeightX = rStartX + dirX * self.sideWatchDirSize
			local rHeightZ = rStartZ + dirZ * self.sideWatchDirSize
			local leftFruit = Utils.getFruitArea(fruitType, lStartX, lStartZ, lWidthX, lWidthZ, lHeightX, lHeightZ, hasFruitPreparer)
			local rightFruit = Utils.getFruitArea(fruitType, rStartX, rStartZ, rWidthX, rWidthZ, rHeightX, rHeightZ, hasFruitPreparer)
			if leftFruit > 0 or rightFruit > 0 then
				if leftFruit > rightFruit then
					turnLeft = true
				else
					turnLeft = false
				end
			else
				self:stopAIThreshing()
				return
			end
			local targetX, targetZ = self.aiThreshingTargetX, self.aiThreshingTargetZ
			local markerSideOffset
			if turnLeft then
				markerSideOffset, _, _ = worldToLocal(self.aiTreshingDirectionNode, lInX, lInY, lInZ)
			else
				markerSideOffset, _, _ = worldToLocal(self.aiTreshingDirectionNode, rInX, rInY, rInZ)
			end
			markerSideOffset = 2 * markerSideOffset
			local areaOverlap = math.min(threshWidth * (1 - self.aiTurnThreshWidthScale), self.aiTurnThreshWidthMaxDifference)
			if markerSideOffset > 0 then
				markerSideOffset = math.max(markerSideOffset - areaOverlap, 0.01)
			else
				markerSideOffset = math.min(markerSideOffset + areaOverlap, -0.01)
			end
			local x, z = Utils.projectOnLine(x, z, targetX, targetZ, dirX, dirZ)
			local x1,y1,z1 = getWorldTranslation(self.aiTreshingDirectionNode);
			local dirX1, dirZ1 = self.aiThreshingDirectionX, self.aiThreshingDirectionZ;
            local sideX1, sideZ1 = -dirZ1, dirX1;
			
			if turnLeft then
				if self.haeckseldolly then
					self.TargetXb = x-sideX*markerSideOffset;
					self.TargetZb = z-sideZ*markerSideOffset;
					local kX = x1 + sideX1*1.5 + dirX1 * 6;
					local kZ = z1 + sideZ1*1.5 + dirZ1 * 6;
					newTargetX = kX ;
					newTargetY = y;
					newTargetZ = kZ ;
				else
					newTargetX = x-sideX*markerSideOffset;
					newTargetY = y;
					newTargetZ = z-sideZ*markerSideOffset;
				end;
            else
				if self.haeckseldolly then
				    self.TargetXb = x-sideX*markerSideOffset;
					self.TargetZb = z-sideZ*markerSideOffset;
					local kX = x1 - sideX1*1.5 + dirX1 * 6;
					local kZ = z1 - sideZ1*1.5 + dirZ1 * 6;
					newTargetX = kX ;
					newTargetY = y;
					newTargetZ = kZ ;
				else
					newTargetX = x-sideX*markerSideOffset;
					newTargetY = y;
					newTargetZ = z-sideZ*markerSideOffset;
				end;
            end;
            self.aiThreshingDirectionX = -dirX;
            self.aiThreshingDirectionZ = -dirZ;
			if self.haeckseldolly then
				self.turnStage = 5;
			else
				self.turnStage = 1;
			end
            
            self.aiRescueTimer = self.aiRescueTimeout;
            self.turnStageTimer = self.turnStage1Timeout;
            self.aiThreshingTargetBeforeTurnX = self.aiThreshingTargetX;
            self.aiThreshingTargetBeforeTurnZ = self.aiThreshingTargetZ;
            self.waitForTurnTime = self.time + self.waitForTurnTimeout;
			self:setAIImplementsMoveDown(false)
            self.allowsThreshing = false;
			updateWheels = false;
		end
	else
		local x, y, z = getWorldTranslation(self.aiTreshingDirectionNode)
		local dirX, dirZ = self.aiThreshingDirectionX, self.aiThreshingDirectionZ
		local targetX, targetZ = self.aiThreshingTargetX, self.aiThreshingTargetZ
		local dx, dz = x - targetX, z - targetZ
		local dot = dx * dirX + dz * dirZ
		local projTargetX = targetX + dirX * dot
		local projTargetZ = targetZ + dirZ * dot
		newTargetX = projTargetX + self.aiThreshingDirectionX * self.lookAheadDistance
		newTargetY = y
		newTargetZ = projTargetZ + self.aiThreshingDirectionZ * self.lookAheadDistance
	end
	if updateWheels then
		local lx, lz = AIVehicleUtil.getDriveDirection(self.aiTreshingDirectionNode, newTargetX, newTargetY, newTargetZ)
		if self.turnStage == 2 and math.abs(lx) < 0.1 then
			AICombine.switchToTurnStage3(self)
			moveForwards = true
		end
		AIVehicleUtil.driveInDirection(self, dt, 25, 0.5, 0.5, 20, true, moveForwards, lx, lz, speedLevel, 0.9)
		local maxlx = 0.7071067
		local colDirX = lx
		local colDirZ = lz
		if maxlx < colDirX then
			colDirX = maxlx
			colDirZ = 0.7071067
		elseif colDirX < -maxlx then
			colDirX = -maxlx
			colDirZ = 0.7071067
		end
		for triggerId, _ in pairs(self.numCollidingVehicles) do
			AIVehicleUtil.setCollisionDirection(self.aiTreshingDirectionNode, triggerId, colDirX, colDirZ)
		end
	end
	self.aiThreshingTargetX = newTargetX
	self.aiThreshingTargetZ = newTargetZ
end

AICombine.updateAIMovement = Utils.overwrittenFunction( AICombine.updateAIMovement, AICombineDolly.updateAIMovement );


function AICombineDolly:draw()
end