-- @ Autor  Tobias F. (John Deere 6930)
-- @ Last Edit  02/11/2011
-- @ history:
		--01/08/2011 - initializing Specialization
		--02/11/2011 - fixing multiplayererror
-- InvertDrivingDirection
-- Specialization to invert the DrivingDirection
--[[XML Data:
<invertSteering rootNode="" clip="" speedScale=""/> ]]
 
InvertDrivingDirection = {};

local InvertDrivingDirection_directory = g_currentModDirectory;

function InvertDrivingDirection.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(Motorized, specializations);
end;

function InvertDrivingDirection:load(xmlFile)
	self.invertDD = InvertDrivingDirection.invertDD;
	self.invertDDDirectory = InvertDrivingDirection_directory;
	self.ddIsInverted = false;
	self.lastAcceleration = 0;
	self.invertTimeOut = 0;
	self.showWarningTime = 0;
	self.invertDDAnimation = {};
	self.invertDDAnimation.animRootNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.invertSteering#rootNode"));
	if self.invertDDAnimation.animRootNode ~= nil and self.invertDDAnimation.animRootNode ~= 0 then
		self.invertDDAnimation.animCharSet = getAnimCharacterSet(self.invertDDAnimation.animRootNode);
		if self.invertDDAnimation.animCharSet ~= 0 then
			local clip = getAnimClipIndex(self.invertDDAnimation.animCharSet, getXMLString(xmlFile, "vehicle.invertSteering#clip"));
			assignAnimTrackClip(self.invertDDAnimation.animCharSet, 0, clip);
			setAnimTrackLoopState(self.invertDDAnimation.animCharSet, 0, false);
			self.invertDDAnimation.animSpeedScale = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.invertSteering#speedScale"), 1);
			self.invertDDAnimation.animDuration = getAnimClipDuration(self.invertDDAnimation.animCharSet, clip);
		end;
	end;
end;

function InvertDrivingDirection:delete()
end;

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

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

function InvertDrivingDirection:update(dt)
	if self:getIsActiveForInput() then
		if InputBinding.hasEvent(InputBinding.INVERTDRIVINGDIRECTION) and self.invertTimeOut <= self.time then
			self:invertDD(not self.ddIsInverted);
		end;
	end;
	if self:getIsActive() then
		if self.invertTimeOut > self.time then
			local animCharSet = self.invertDDAnimation.animCharSet;
			if self.ddIsInverted then
				if self.invokeIgnition ~= nil then
					self:invokeIgnition(false);
				end;
				if animCharSet ~= 0 then
				    if getAnimTrackTime(animCharSet, 0) < 0.0 then
						setAnimTrackTime(animCharSet, 0, 0.0);
					end;
					setAnimTrackSpeedScale(animCharSet, 0, self.invertDDAnimation.animSpeedScale);
					enableAnimTrack(animCharSet, 0);
				end;	
			else
				if self.invokeIgnition ~= nil then
					self:invokeIgnition(false);
				end;
				if animCharSet ~= 0 then
					if getAnimTrackTime(animCharSet, 0) > self.invertDDAnimation.animDuration then
						setAnimTrackTime(animCharSet, 0, self.invertDDAnimation.animDuration);
					end;
					setAnimTrackSpeedScale(animCharSet, 0, -self.invertDDAnimation.animSpeedScale);
					enableAnimTrack(animCharSet, 0);
				end;	
			end;		
			if self.isServer then
				Steerable.updateVehiclePhysics(self, 0, self.axisForwardIsAnalog, 0, self.axisSideIsAnalog, dt);
			end;
		end;		
	end;
end;

function InvertDrivingDirection:readStream(streamId, connection)
    local ddIsInverted = streamReadBool(streamId);
	if ddIsInverted ~= self.ddIsInverted then
		self:invertDD(ddIsInverted, true);
	end;
end;

function InvertDrivingDirection:writeStream(streamId, connection)
    streamWriteBool(streamId, self.ddIsInverted);
end;

function InvertDrivingDirection:draw()
	if self.showWarningTime > self.time then
		g_currentMission:addWarning(g_i18n:getText("warning_ai_active"), 0, 0.03);
	end;
	if not self.ddIsInverted  then
		g_currentMission:addHelpButtonText(g_i18n:getText("ACTIVATE_INVERTDRIVING"), InputBinding.INVERTDRIVINGDIRECTION);
	else
		g_currentMission:addHelpButtonText(g_i18n:getText("DEACTIVATE_INVERTDRIVING"), InputBinding.INVERTDRIVINGDIRECTION);
	end;
end;

function InvertDrivingDirection:invertDD(ddIsInverted, noEventSend)
	InvertDrivingDirectionEvent.sendEvent(self, ddIsInverted, noEventSend)

	self:dismiss();
	self:stopAITractor();

	self.invertTimeOut = self.time+10+self.invertDDAnimation.animDuration;
	self.ddIsInverted = ddIsInverted;

	for _,wheel in pairs(self.wheels) do
		wheel.rotSpeed = -wheel.rotSpeed;
		if self.isRealistic then
			local tmp = wheel.realRotMinSpeed;
			wheel.realRotMinSpeed = -wheel.realRotMaxSpeed;
			wheel.realRotMaxSpeed = -tmp;
		end;
	end;
	
	if self.aiTractorDirectionNode ~= nil then
		if self.invertDDAiNode == nil then
			self.invertDDAiNode     = self.aiTractorDirectionNode;
			self.invertDDAiNodeBack = createTransformGroup("invertDDAiNodeBack");
			link(self.invertDDAiNode,self.invertDDAiNodeBack);
			setRotation(self.invertDDAiNodeBack,0,math.pi,0);
		end;
		if self.ddIsInverted then
			self.aiTractorDirectionNode = self.invertDDAiNodeBack;
		else
			self.aiTractorDirectionNode = self.invertDDAiNode;
		end;
	end;
end;

local oldSteerableCalculateRealAcceleration = Steerable.calculateRealAcceleration;
Steerable.calculateRealAcceleration = function(self, acceleration, dt)

	if self.isRealistic or self.invertDDDirectory ~= InvertDrivingDirection_directory or not self.ddIsInverted then
		return oldSteerableCalculateRealAcceleration(self, acceleration, dt);
	end;

	return - oldSteerableCalculateRealAcceleration(self, acceleration, dt);
end;

InvertDrivingDirectionEvent = {};
InvertDrivingDirectionEvent_mt = Class(InvertDrivingDirectionEvent, Event);

InitEventClass(InvertDrivingDirectionEvent, "InvertDrivingDirectionEvent");

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

function InvertDrivingDirectionEvent:new(object, ddIsInverted)
    local self = InvertDrivingDirectionEvent:emptyNew()
    self.object = object;
	self.ddIsInverted = ddIsInverted;
    return self;
end;

function InvertDrivingDirectionEvent:readStream(streamId, connection)
    local id = streamReadInt32(streamId);
	self.ddIsInverted = streamReadBool(streamId);
    self.object = networkGetObject(id);
    self:run(connection);
end;

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

function InvertDrivingDirectionEvent:run(connection)
	self.object:invertDD(self.ddIsInverted, true);
    if not connection:getIsServer() then
        g_server:broadcastEvent(InvertDrivingDirectionEvent:new(self.object, self.ddIsInverted), nil, connection, self.object);
    end;
end;

function InvertDrivingDirectionEvent.sendEvent(vehicle, ddIsInverted, noEventSend)
	if ddIsInverted ~= vehicle.ddIsInverted then
		if noEventSend == nil or noEventSend == false then
			if g_server ~= nil then
				g_server:broadcastEvent(InvertDrivingDirectionEvent:new(vehicle, ddIsInverted), nil, nil, vehicle);
			else
				g_client:getServerConnection():sendEvent(InvertDrivingDirectionEvent:new(vehicle, ddIsInverted));
			end;
		end;
	end;
end;

