--
-- UniaPilmetRex
--
-- @author: 	Burner
-- @date: 		14.07.2015
--

UniaPilmetRex = {}

function UniaPilmetRex.prerequisitesPresent(specializations)
   return SpecializationUtil.hasSpecialization(Cylindered, specializations)
end

function UniaPilmetRex:load(xmlFile)
	self.setTrailControl = SpecializationUtil.callSpecializationsFunction("setTrailControl");
	self.trailControl = false;

	self.trailControlInfo = {};
	
	local trailControlWheel = getXMLInt(xmlFile, "vehicle.trailControl#wheelIndex");
    if trailControlWheel ~= nil then
        self.trailControlInfo.wheelIndex = trailControlWheel;
		local wheel = self.wheels[trailControlWheel];
		wheel.steeringAxleScaleBackup = wheel.steeringAxleScale;
    end;
	
	local trailControlMovingTool = getXMLInt(xmlFile, "vehicle.trailControl#movingToolIndex");
    if trailControlMovingTool ~= nil then
        self.trailControlInfo.movingToolIndex = trailControlMovingTool;    
    end;
	
	self.trailControlInfo.dependentParts = {};
    local j=0;
    while true do
        local refBaseName = string.format("vehicle.trailControl.dependentPart(%d)", j);
        if not hasXMLProperty(xmlFile, refBaseName) then
            break;
        end;
        local node = Utils.indexToObject(self.components, getXMLString(xmlFile, refBaseName.."#index"));
		local transOffset = Utils.getVectorNFromString(getXMLString(xmlFile, refBaseName.."#transOffset"), 3);
		if node ~= nil and transOffset ~= nil then
			local dependentPart = {};
			dependentPart.node = node;
			dependentPart.transOffset = transOffset;
			table.insert(self.trailControlInfo.dependentParts, dependentPart);
		end;
		j = j+1;
	end;
end

function UniaPilmetRex:delete()
end

function UniaPilmetRex:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)
	local trailControl = getXMLBool(xmlFile, key.."#trailControl");
	if trailControl ~= nil then
		self:setTrailControl(trailControl);
	end;
	return BaseMission.VEHICLE_LOAD_OK;
end

function UniaPilmetRex:getSaveAttributesAndNodes(nodeIdent)
	local attributes = 'trailControl="'..tostring(self.trailControl)..'"';
	return attributes, nil;
end

function UniaPilmetRex:readStream(streamId, connection)
	local isTrailControlEnabled = streamReadBool(streamId);
	self:setTrailControl(isTrailControlEnabled, true);
end;

function UniaPilmetRex:writeStream(streamId, connection)
	streamWriteBool(streamId, self.trailControl);
end;

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

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

function UniaPilmetRex:update(dt)
	if self:getIsActiveForInput(false) then
		if InputBinding.hasEvent(InputBinding.UniaPilmetRex_TrailControl) then
			self:setTrailControl(not self.trailControl);
		end;
	end;
	
	-- smooth toggle
	local wheel = self.wheels[self.trailControlInfo.wheelIndex];
	if wheel.steeringAxleScaleBackup ~= 0 then
		if self.trailControl then
			wheel.steeringAxleScale = math.min(wheel.steeringAxleScale + (dt/2000), wheel.steeringAxleScaleBackup);
		else
			wheel.steeringAxleScale = math.max(wheel.steeringAxleScale - (dt/2000), 0);
		end;
	end;
	
	-- translate dependent parts
	if self.trailControlInfo.dependentParts ~= nil then
		for _, dependentPart in pairs(self.trailControlInfo.dependentParts) do
			local scale = wheel.steeringAngle / wheel.steeringAxleRotMax;
			local curTrans = {dependentPart.transOffset[1]*scale, dependentPart.transOffset[2]*scale, dependentPart.transOffset[3]*scale}
			setTranslation(dependentPart.node, unpack(curTrans));
		end
	end;

	-- update attacher position
	if self.isServer then
		Cylindered.setDirty(self, self.movingTools[self.trailControlInfo.movingToolIndex]);
	end;
end;

function UniaPilmetRex:updateTick(dt)
end;

function UniaPilmetRex:draw()
	if self.trailControl then
		g_currentMission:addHelpButtonText(string.format(g_i18n:getText(self.turnOffText), g_i18n:getText('UniaPilmetRex_TrailControl')), InputBinding.UniaPilmetRex_TrailControl);
	else
		g_currentMission:addHelpButtonText(string.format(g_i18n:getText(self.turnOnText), g_i18n:getText('UniaPilmetRex_TrailControl')), InputBinding.UniaPilmetRex_TrailControl);
	end
end;

function UniaPilmetRex:onEnter()
end;

function UniaPilmetRex:onLeave()
end;

function UniaPilmetRex:setTrailControl(isTrailControlEnabled, noEventSend)
	SetTrailControlEvent.sendEvent(self, isTrailControlEnabled, noEventSend)
	self.trailControl = isTrailControlEnabled;
end;

SetTrailControlEvent = {};
SetTrailControlEvent_mt = Class(SetTrailControlEvent, Event);
  
InitEventClass(SetTrailControlEvent, "SetTrailControlEvent");
  
function SetTrailControlEvent:emptyNew()
	local self = Event:new(SetTrailControlEvent_mt);
	self.className="SetTrailControlEvent";
	return self;
end;
  
function SetTrailControlEvent:new(object, isTrailControlEnabled)
	local self = SetTrailControlEvent:emptyNew()
	self.object = object;
	self.isTrailControlEnabled = isTrailControlEnabled;
	return self;
end;
  
function SetTrailControlEvent:readStream(streamId, connection)
	local id = streamReadInt32(streamId);
	self.isTrailControlEnabled = streamReadBool(streamId);
	self.object = networkGetObject(id);
	self:run(connection);
end;
  
function SetTrailControlEvent:writeStream(streamId, connection)
	streamWriteInt32(streamId, networkGetObjectId(self.object));
	streamWriteBool(streamId, self.isTrailControlEnabled);
end;
  
function SetTrailControlEvent:run(connection)
	if not connection:getIsServer() then
		g_server:broadcastEvent(self, false, connection, self.object);
	end;
	self.object:setTrailControl(self.isTrailControlEnabled, true);
end;
  
function SetTrailControlEvent.sendEvent(vehicle, isTrailControlEnabled, noEventSend)
	if isTrailControlEnabled ~= vehicle.trailControl then
		if noEventSend == nil or noEventSend == false then
			if g_server ~= nil then
				g_server:broadcastEvent(SetTrailControlEvent:new(vehicle, isTrailControlEnabled), nil, nil, vehicle);
			else
				g_client:getServerConnection():sendEvent(SetTrailControlEvent:new(vehicle, isTrailControlEnabled));
			end;
		end;
	end;
end;