--
-- DrivingLine
-- Specialization for driving lines of sowing machines
--
--	@author:		gotchTOM
--	@date: 			28-Apr-2013
--	@version: 		v1.15
--	@history:		v1.0 	- initial implementation (17-Jun-2012)
--					v1.15 	- replace limitToField
--							- manualDrivingLine	
--							- movable HUD
--							- compatible with ZZZ_HiredWorkerConsumesFuelSeeds.zip
--							- self.backUpMoveDown
--							- attacherVehicle bugfix
--							- mousecursor detach bugfix	
--							- camera movement bugfix
--							- mousecursor AI problem bugfix	
--							- compatible with Kuhn Moduliner (self.drivemark)
--							- compatible with Farmet_Excelent_Premium_6 (self.seederIsDown)
--							- LS 2013 compatible


DrivingLine = {};

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

function DrivingLine:load(xmlFile)

	self.setDrivingLine = SpecializationUtil.callSpecializationsFunction("setDrivingLine");
	local numdrivingLines = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.drivingLines#count"), 0);
	self.drivingLines = {}
    for i=1, numdrivingLines do
        self.drivingLines[i] = {};
        local areanamei = string.format("vehicle.drivingLines.drivingLine" .. "%d", i); 
        self.drivingLines[i].start = Utils.indexToObject(self.components, getXMLString(xmlFile, areanamei .. "#startIndex"));
        self.drivingLines[i].width = Utils.indexToObject(self.components, getXMLString(xmlFile, areanamei .. "#widthIndex"));
        self.drivingLines[i].height = Utils.indexToObject(self.components, getXMLString(xmlFile, areanamei .. "#heightIndex"));
    end;
	if numdrivingLines > 0 then
		self.drivingLinePresent = true;
	end;
	self.drivingLineActiv = false;
	self.dlHUDisActive = false;
	self.manualDrivingLine = true;
	self.backUpMoveDown = false;
	
	self.currentDrive = 1;
	self.smWorkwith = 3;
	self.nSMworkwith = 3;
	self.dlWarning = 0;
	self.dlCultivatorDelay = 0;
	
	
	-- HUD
	local overlayfile = Utils.getFilename("dlHUD.png", self.baseDirectory);
	self.dlOverlay = createImageOverlay(overlayfile);
	setOverlayColor(self.dlOverlay, 1, 1, 1, 1);
	
	self.dlHudBaseX = 0.85;
	self.dlHudBaseY = 0.63;
	self.dlHudMove = false;
	self.mouseEnabled = false;
	self.checkOnLeave = false;
end;

function DrivingLine:delete()
end;

function DrivingLine:readStream(streamId, connection)

	self.drivingLineActiv = streamReadBool(streamId);
end;

function DrivingLine:writeStream(streamId, connection)

	streamWriteBool(streamId, self.drivingLineActiv);
end;

function DrivingLine:mouseEvent(posX, posY, isDown, isUp, button)
	
	-- HUD move
	if self.dlHudMove then
		self.dlHudBaseX = posX;
		self.dlHudBaseY = posY;
	end;
	local dlHudchangedJet = false;
	if self.dlHudMove and isDown and button == 1 then
		self.dlHudMove = false;
		dlHudchangedJet = true;
	end;
	if isDown and button == 1 and dlHudchangedJet ~= true then
		if (self.dlHudBaseX-0.10) < posX and posX < (self.dlHudBaseX+0.06) and (self.dlHudBaseY-0.01) < posY and posY < (self.dlHudBaseY+0.01) then
			self.dlHudMove = true;
		end;
	end;
	
	if self.dlHUDisActive and isDown and button == 1 then
		-- switch manual-automatic
		if (self.dlHudBaseX+0.14) > posX and (self.dlHudBaseX+0.10) < posX and (self.dlHudBaseY-0.01) > posY and (self.dlHudBaseY-0.04) < posY then
			self.manualDrivingLine = not self.manualDrivingLine;
		end;
		if not self.manualDrivingLine then
			-- set current drive
			if (self.dlHudBaseX+0.12) > posX and (self.dlHudBaseX+0.10) < posX and (self.dlHudBaseY-0.04) > posY and (self.dlHudBaseY-0.07) < posY then
				self.currentDrive = self.currentDrive + 1;
			end;
			if (self.dlHudBaseX+0.13) > posX and (self.dlHudBaseX+0.12) < posX and (self.dlHudBaseY-0.04) > posY and (self.dlHudBaseY-0.07) < posY then
				self.currentDrive = self.currentDrive - 1;
			end;
			-- set workwith of sowing machine
			if (self.dlHudBaseX+0.12) > posX and (self.dlHudBaseX+0.10) < posX and (self.dlHudBaseY-0.10) > posY and (self.dlHudBaseY-0.13) < posY then
				if self.smWorkwith < 20 then
					self.smWorkwith = self.smWorkwith + 1;
				else
					self.smWorkwith = 3;
					self.dlWarning = self.time + 250;
				end;	
			end;
			if (self.dlHudBaseX+0.13) > posX and (self.dlHudBaseX+0.12) < posX and (self.dlHudBaseY-0.10) > posY and (self.dlHudBaseY-0.13) < posY then
				if self.smWorkwith > 3 then
					self.smWorkwith = self.smWorkwith - 1;
				else
					self.smWorkwith = 20;
					self.dlWarning = self.time + 250;
				end;
			end;
			-- set workwith of sprayer
			if (self.dlHudBaseX+0.12) > posX and (self.dlHudBaseX+0.10) < posX and (self.dlHudBaseY-0.13) > posY and (self.dlHudBaseY-0.16) < posY then
				if self.spWorkwith < 57 then
					self.nSMworkwith = self.nSMworkwith + 1;
				else
					self.nSMworkwith = 3;
					self.dlWarning = self.time + 250;
				end;
			end;
			if (self.dlHudBaseX+0.13) > posX and (self.dlHudBaseX+0.12) < posX and (self.dlHudBaseY-0.13) > posY and (self.dlHudBaseY-0.16) < posY then
				if self.nSMworkwith > 3 and self.spWorkwith < 61 then
					self.nSMworkwith = self.nSMworkwith - 1;
				else
					self.nSMworkwith = 3;
					self.dlWarning = self.time + 250;
				end;	
			end;
		end;	
	end;
end;

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

function DrivingLine:onAttach(attacherVehicle)
    
	if self.mouseEnabled then
		-- activate cursor
		InputBinding.setShowMouseCursor(true);
		-- deactivate camera
		if attacherVehicle ~= nil then
			if attacherVehicle.cameras[attacherVehicle.camIndex] ~= nil then
				attacherVehicle.cameras[attacherVehicle.camIndex].isActivated = false;
			end;
		end;
	end;
end;

function DrivingLine:onDetach(attacherVehicle)

	if self.mouseEnabled then
		-- deactivate cursor
		InputBinding.setShowMouseCursor(false);
		-- activate camera
		if attacherVehicle ~= nil then
			if attacherVehicle.cameras[attacherVehicle.camIndex] ~= nil then
				attacherVehicle.cameras[attacherVehicle.camIndex].isActivated = true;
			end;
		end;
	end;	
end;


function DrivingLine:update(dt)

	if self:getIsActiveForInput() then
		if self.drivingLinePresent then				
			-- switch driving line
			if InputBinding.hasEvent(InputBinding.DRIVINGLINE) then
				if self.drivingLineActiv then
					self:setDrivingLine(false);
				else
					self:setDrivingLine(true);
				end;
			end;
			-- switch HUD
			if InputBinding.hasEvent(InputBinding.DRIVINGLINE_HUD) then
				self.dlHUDisActive = not self.dlHUDisActive;
				self.mouseEnabled = self.dlHUDisActive;
				InputBinding.setShowMouseCursor(self.dlHUDisActive);
			end;
			-- show/hide mouse cursor
			if self.dlHUDisActive then
				if InputBinding.hasEvent(InputBinding.DRIVINGLINE_MOUSECURSOR) then
					if self.mouseEnabled then
						self.mouseEnabled = false;
						InputBinding.setShowMouseCursor(false);
					else
						self.mouseEnabled = true;
						InputBinding.setShowMouseCursor(true);
					end;
				end;
			end;
			-- activate/deactivate camera
			if self.attacherVehicle ~= nil then
				if self.attacherVehicle.cameras[self.attacherVehicle.camIndex] ~= nil then
					self.attacherVehicle.cameras[self.attacherVehicle.camIndex].isActivated = not self.mouseEnabled;
				end;
			end;
		end;	
	end;
	-- show/hide mouse cursor onLeave/onEnter
	if self.attacherVehicle ~= nil then
		if self.attacherVehicle.isControlled and not self.checkOnLeave then
		-- print("drivingLine:onEnter")
			self.checkOnLeave = true;
		elseif not self.attacherVehicle.isControlled and self.checkOnLeave then
		-- print("drivingLine:onLeave")
			InputBinding.setShowMouseCursor(false);
			self.mouseEnabled = false;
			self.checkOnLeave = false;
		end;
	end;	
end;

function DrivingLine:updateTick(dt)
    
	if self:getIsActive() then
		if self.drivingLinePresent then
			if self.isServer then
				if self.drivingLineActiv and (self.sowingMachineHasGroundContact or self.seederIsDown) and self.isTurnedOn then	
					local drivingLinesSend = {};
					if self.dlCultivatorDelay <= self.time then	
						for _,area in pairs(self.drivingLines) do
							local x,y,z = getWorldTranslation(area.start);
							local x1,y1,z1 = getWorldTranslation(area.width);
							local x2,y2,z2 = getWorldTranslation(area.height);
							table.insert(drivingLinesSend, {x,z,x1,z1,x2,z2});
							if table.getn(drivingLinesSend) > 0 then
								CultivatorAreaEvent.runLocally(drivingLinesSend, true);
								g_server:broadcastEvent(CultivatorAreaEvent:new(drivingLinesSend, true));
							end;
						end;
					end;	
				end;
			end;	
			if not self.manualDrivingLine then
				self.spWorkwith = self.smWorkwith * self.nSMworkwith 
				self.maxn_drive = self.spWorkwith/self.smWorkwith;
				self.num_DrivingLine = (self.maxn_drive + 1) / 2;											
				if self.currentDrive > self.maxn_drive then
					self.currentDrive = 1;
				elseif self.currentDrive < 1 then
					self.currentDrive = self.maxn_drive;
				end;					
				if self.currentDrive == self.num_DrivingLine and not self.drivingLineActiv then
					self:setDrivingLine(true);
				elseif self.currentDrive ~= self.num_DrivingLine and self.drivingLineActiv then
					self:setDrivingLine(false);
				end;
				if self:getIsActiveForInput() then	
					if self.attacherVehicle ~= nil and not self.attacherVehicle.isHired then
						local implement = self.attacherVehicle.selectedImplement;
						if implement ~= nil then
							local jointDesc = self.attacherVehicle.attacherJoints[implement.jointDescIndex];
							local moveDown = jointDesc.moveDown;
							if self.backUpMoveDown ~= moveDown then
								if not jointDesc.moveDown then
									self.currentDrive = self.currentDrive + 1;
									self.dlCultivatorDelay = self.time + 2000;
								end;
								self.backUpMoveDown = moveDown;								
							end;	
						end;
					end;
				end;	
			end;
		end;	
    end;
end;

function DrivingLine:setIsTurnedOn()
    
	if self.attacherVehicle ~= nil then	
		if not self.attacherVehicle.isHired then	
			if not self.manualDrivingLine then	
				if not self.isTurnedOn then
					self.currentDrive = self.currentDrive + 1;
				end;
			end;	
		end;
	end;	
end;

function DrivingLine:aiLower()
    
	if not self.manualDrivingLine then
		self.currentDrive = self.currentDrive + 1;
	end;	
end;

function DrivingLine:draw()

	if self.drivingLinePresent then
		if self.manualDrivingLine then
			if self.drivingLineActiv then	
				g_currentMission:addHelpButtonText(g_i18n:getText("DRIVINGLINE_OFF"), InputBinding.DRIVINGLINE);
			else
				g_currentMission:addHelpButtonText(g_i18n:getText("DRIVINGLINE_ON"), InputBinding.DRIVINGLINE);
			end;
		end;
		
		setTextBold(false);
		if self.dlHUDisActive then
			g_currentMission:addHelpButtonText(g_i18n:getText("DRIVINGLINE_HUD_OFF"), InputBinding.DRIVINGLINE_HUD);
			-- if self.mouseEnabled then
				-- g_currentMission:addHelpButtonText(g_i18n:getText("DRIVINGLINE_MOUSECURSOR"), InputBinding.DRIVINGLINE_MOUSECURSOR);
			-- else
				-- g_currentMission:addHelpButtonText(g_i18n:getText("DRIVINGLINE_MOUSECURSOR"), InputBinding.DRIVINGLINE_MOUSECURSOR);
			-- end;
			if self.dlWarning > self.time then
				setTextColor(1,0.2,0.2,1);
			else
				setTextColor(1,1,1,1);
			end;
			renderText((self.dlHudBaseX-0.10), (self.dlHudBaseY-0.01), 0.025, g_i18n:getText("DRIVINGLINE_MOVEHUD"));
			renderText((self.dlHudBaseX+0.10), (self.dlHudBaseY-0.04), 0.025, "< >");
			if not self.manualDrivingLine then
				renderText((self.dlHudBaseX-0.10), (self.dlHudBaseY-0.04), 0.025, g_i18n:getText("DRIVINGLINE_AUTOMATIC"));
				renderText((self.dlHudBaseX-0.10), (self.dlHudBaseY-0.07), 0.025, g_i18n:getText("DRIVINGLINE_CURRENTDRIVE").." "..tostring(self.currentDrive).." ("..tostring(self.maxn_drive)..")");
				renderText((self.dlHudBaseX+0.10),(self.dlHudBaseY-0.07), 0.025, "+ -");
				renderText((self.dlHudBaseX-0.10), (self.dlHudBaseY-0.10), 0.02, g_i18n:getText("DRIVINGLINE_NUMDRIVINGLINE").." "..tostring(self.num_DrivingLine));
				
				
				renderText((self.dlHudBaseX-0.10), (self.dlHudBaseY-0.13), 0.025, g_i18n:getText("DRIVINGLINE_WORKWIDTHSOWING").." "..tostring(self.smWorkwith));
				renderText((self.dlHudBaseX+0.10),(self.dlHudBaseY-0.13), 0.025, "+ -");
				
				renderText((self.dlHudBaseX-0.10), (self.dlHudBaseY-0.16), 0.025, g_i18n:getText("DRIVINGLINE_WORKWIDTHSPRAYER").." "..tostring(self.spWorkwith));
				renderText((self.dlHudBaseX+0.10),(self.dlHudBaseY-0.16), 0.025, "+ -");
				
				renderOverlay(self.dlOverlay, (self.dlHudBaseX-0.11), (self.dlHudBaseY-0.18), 0.25, 0.21);
			else
				renderText((self.dlHudBaseX-0.10), (self.dlHudBaseY-0.04), 0.025, g_i18n:getText("DRIVINGLINE_MANUAL"));
				renderOverlay(self.dlOverlay, (self.dlHudBaseX-0.11), (self.dlHudBaseY-0.06), 0.25, 0.08);
			end;
		else
			g_currentMission:addHelpButtonText(g_i18n:getText("DRIVINGLINE_HUD_ON"), InputBinding.DRIVINGLINE_HUD);
		end;
		
	end;
end;

function DrivingLine:setDrivingLine(drivingLineActiv, noEventSend)

	if noEventSend == nil or noEventSend == false then	
		SetDrivingLineEvent.sendEvent(self, drivingLineActiv, noEventSend); 
	end;	
	self.drivingLineActiv = drivingLineActiv;
	
	
	-- Kuhn Moduliner
	if self.drivemark ~= nil then
		self.drivemark = self.drivingLineActiv;
	end;
			

end;



SetDrivingLineEvent = {};
SetDrivingLineEvent_mt = Class(SetDrivingLineEvent, Event);

InitEventClass(SetDrivingLineEvent, "SetDrivingLineEvent");

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

function SetDrivingLineEvent:new(vehicle, drivingLineActiv)

    local self = SetDrivingLineEvent:emptyNew()
    self.vehicle = vehicle;
	self.drivingLineActiv = drivingLineActiv;
    return self;
end;

function SetDrivingLineEvent:readStream(streamId, connection) 

    local id = streamReadInt32(streamId); 
	self.drivingLineActiv = streamReadBool(streamId);  
    self.vehicle = networkGetObject(id); 
    self:run(connection);
	-- print("readStream! self.drivingLineActiv: "..tostring(self.drivingLineActiv).." self.vehicle: "..tostring(self.vehicle).." streamId: "..tostring(streamId).." connection: "..tostring(connection)) --!!!

end;

function SetDrivingLineEvent:writeStream(streamId, connection) 
  
    streamWriteInt32(streamId, networkGetObjectId(self.vehicle));	
	streamWriteBool(streamId, self.drivingLineActiv);
	-- print("writeStream! self.drivingLineActiv: "..tostring(self.drivingLineActiv).." self.vehicle: "..tostring(self.vehicle).." streamId: "..tostring(streamId).." connection: "..tostring(connection)) --!!!

end;

function SetDrivingLineEvent:run(connection) 
  
	if not connection:getIsServer() then	
		for k, v in pairs(g_server.clientConnections) do
			if v ~= connection and not v:getIsLocal() then
				v:sendEvent(SetDrivingLineEvent:new(self.vehicle, self.drivingLineActiv));
			end;
		end;
	end;	
	self.vehicle:setDrivingLine(self.drivingLineActiv, true); 
	-- print("SetDrivingLineEvent:run(connection)") --!!!
end;

function SetDrivingLineEvent.sendEvent(vehicle, drivingLineActiv, noEventSend)  
		
	if g_server ~= nil then  
		g_server:broadcastEvent(SetDrivingLineEvent:new(vehicle, drivingLineActiv), nil, nil, vehicle);
		-- print("sendEvent: g_server:broadcast Event! drivingLineActiv: "..tostring(drivingLineActiv).." vehicle: "..tostring(vehicle).." noEventSend: "..tostring(noEventSend)) --!!!
		
	else  
		g_client:getServerConnection():sendEvent(SetDrivingLineEvent:new(vehicle, drivingLineActiv));
		-- print("sendEvent: g_client:send Event! drivingLineActiv: "..tostring(drivingLineActiv).." vehicle: "..tostring(vehicle).." noEventSend: "..tostring(noEventSend)) --!!!
		
	end;
end;