--
-- BJR_AdjustableAttacher
-- Specialization for BJR_AdjustableAttacher mod
--
-- @author  	JoXXer, rf928
-- @date  		09/03/13
--

BJR_AdjustableAttacher = {};

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

function BJR_AdjustableAttacher:load(xmlFile)

	self.setNewTranslation = SpecializationUtil.callSpecializationsFunction("setNewTranslation");
	
	self.topTrailerAttacher = {};
	self.topTrailerAttacher.index = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.topTrailerAttacher#index"));
	
	local topX, topY, topZ = getTranslation(self.topTrailerAttacher.index);
	self.topTrailerAttacher.origX = topX;
	self.topTrailerAttacher.origY = topY;
	self.topTrailerAttacher.origZ = topZ;
	
	self.topTrailerAttacher.maxTrans = Utils.getNoNil(getXMLFloat(xmlFile,  "vehicle.topTrailerAttacher#maxTransLimit"), 0);
	self.topTrailerAttacher.minTrans = Utils.getNoNil(getXMLFloat(xmlFile,  "vehicle.topTrailerAttacher#minTransLimit"), 0);
	self.topTrailerAttacher.attacherIndex = Utils.getNoNil(getXMLFloat(xmlFile,  "vehicle.topTrailerAttacher#attacherIndex"), 3);
	self.topTrailerAttacher.shouldHide = Utils.getNoNil(getXMLBool(xmlFile,  "vehicle.topTrailerAttacher#shouldHide"), false);
	self.topTrailerAttacher.shouldReset = Utils.getNoNil(getXMLBool(xmlFile,  "vehicle.topTrailerAttacher#shouldReset"), false);
	
	self.lowTrailerAttacher = {};
	self.lowTrailerAttacher.index = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.lowTrailerAttacher#index"));
	
	local lowX, lowY, lowZ = getTranslation(self.lowTrailerAttacher.index);
	self.lowTrailerAttacher.origX = lowX;
	self.lowTrailerAttacher.origY = lowY;
	self.lowTrailerAttacher.origZ = lowZ;
	
	self.lowTrailerAttacher.maxTrans = Utils.getNoNil(getXMLFloat(xmlFile,  "vehicle.lowTrailerAttacher#maxTransLimit"), 0);
	self.lowTrailerAttacher.minTrans = Utils.getNoNil(getXMLFloat(xmlFile,  "vehicle.lowTrailerAttacher#minTransLimit"), 0);
	self.lowTrailerAttacher.attacherIndex = Utils.getNoNil(getXMLFloat(xmlFile,  "vehicle.lowTrailerAttacher#attacherIndex"), 4);
	self.lowTrailerAttacher.shouldHide = Utils.getNoNil(getXMLBool(xmlFile,  "vehicle.lowTrailerAttacher#shouldHide"), false);
	self.lowTrailerAttacher.shouldReset = Utils.getNoNil(getXMLBool(xmlFile,  "vehicle.lowTrailerAttacher#shouldReset"), false);
	
	self.newYTrans = 0;
	self.activeAttacher = nil;
	self.activeAttacherId = 0;
	
	self.moveSpeed = 0.0002;
	
	self.bValidate = false;
end;

function BJR_AdjustableAttacher:delete()
end;

function BJR_AdjustableAttacher:readStream(streamId, connection)
	self.activeAttacherId = streamReadInt8(streamId);
	
	if self.activeAttacherId == 1 then
		local x = streamReadFloat32(streamId);
		local y = streamReadFloat32(streamId);
		local z = streamReadFloat32(streamId);
		setTranslation(self.topTrailerAttacher.index, x, y, z);
	elseif self.activeAttacherId == 2 then
		local x = streamReadFloat32(streamId);
		local y = streamReadFloat32(streamId);
		local z = streamReadFloat32(streamId);
		setTranslation(self.lowTrailerAttacher.index, x, y, z);
	end;
end;

function BJR_AdjustableAttacher:writeStream(streamId, connection)
	streamWriteInt8(streamId, self.activeAttacherId);
	
	if self.activeAttacher ~= nil then
		local x, y, z = getTranslation(self.activeAttacher.index);
		streamWriteFloat32(streamId, x);
		streamWriteFloat32(streamId, y);
		streamWriteFloat32(streamId, z);
	end;
end;

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

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

function BJR_AdjustableAttacher:update(dt)
	if self:getIsActive() then
		if self.activeAttacher ~= nil and self.isClient and self:getIsActiveForInput(false) and not self:hasInputConflictWithSelection() then
			
			local transX, transY, transZ = getTranslation(self.activeAttacher.index);
			
			if InputBinding.isPressed(InputBinding.BJR_RAISE_ATTACHER) then
				if transY <= self.activeAttacher.maxTrans then
					transY = transY + self.moveSpeed * dt;
					self.newYTrans = transY;
					self:setNewTranslation(self.activeAttacherId, self.newYTrans);
				end;
			elseif InputBinding.isPressed(InputBinding.BJR_LOWER_ATTACHER) then
				if transY >= self.activeAttacher.minTrans then
					transY = transY - self.moveSpeed * dt;
					self.newYTrans = transY;
					self:setNewTranslation(self.activeAttacherId, self.newYTrans);
				end;
			end;
		end;
	end;
end;

function BJR_AdjustableAttacher:updateTick(dt)

end;

function BJR_AdjustableAttacher:draw()
	if self.activeAttacher ~= nil then
		g_currentMission:addExtraPrintText(string.format(g_i18n:getText("BJR_ATTACHER_CONTROLS"), self.typeDesc) .. " " .. InputBinding.getKeyNamesOfDigitalAction(InputBinding.BJR_RAISE_ATTACHER) .. "/" .. InputBinding.getKeyNamesOfDigitalAction(InputBinding.BJR_LOWER_ATTACHER));
	end;
end;

function BJR_AdjustableAttacher:onLeave()

end;

function BJR_AdjustableAttacher:onEnter()

end;

function BJR_AdjustableAttacher:attachImplement(implement)
	local jointType = implement.object.attacherJoint.jointType;
	local jointIndex = implement.jointDescIndex;
	
	if jointType == Vehicle.JOINTTYPE_IMPLEMENT then
		if jointIndex == 1 then
			if self.topTrailerAttacher.shouldHide then
				setVisibility(self.topTrailerAttacher.index, false);
			end;
			if self.lowTrailerAttacher.shouldHide then
				setVisibility(self.lowTrailerAttacher.index, false);
			end;
		end;
	elseif jointType == Vehicle.JOINTTYPE_TRAILER or jointType == Vehicle.JOINTTYPE_TRAILERLOW then
		if jointIndex == self.topTrailerAttacher.attacherIndex then
			self.activeAttacherId = 1;
			self.activeAttacher = self.topTrailerAttacher;
		elseif jointIndex == self.lowTrailerAttacher.attacherIndex then
			self.activeAttacherId = 2;
			self.activeAttacher = self.lowTrailerAttacher;
		end;
	end;
end;

function BJR_AdjustableAttacher:detachImplement(implementIndex)
	local implement = self.attachedImplements[implementIndex];
	local jointType = implement.object.attacherJoint.jointType;
	local jointIndex = implement.jointDescIndex;

	if jointType == Vehicle.JOINTTYPE_IMPLEMENT then
		if jointIndex == 1 then
			if self.topTrailerAttacher.shouldHide then
				setVisibility(self.topTrailerAttacher.index, true);
			end;
			if self.lowTrailerAttacher.shouldHide then
				setVisibility(self.lowTrailerAttacher.index, true);
			end;
		end;
	elseif jointType == Vehicle.JOINTTYPE_TRAILER or jointType == Vehicle.JOINTTYPE_TRAILERLOW then
		if self.activeAttacher ~= nil then
			if self.activeAttacher.shouldReset then
				setTranslation(self.activeAttacher.index, self.activeAttacher.origX, self.activeAttacher.origY, self.activeAttacher.origZ);
			end;
		end;
		self.activeAttacherId = 0;
		self.activeAttacher = nil;
	end;
end;

function BJR_AdjustableAttacher:validateAttacherJoint(implement, jointDesc, dt)
	local jointType = implement.object.attacherJoint.jointType;
	local jointIndex = implement.jointDescIndex;
	
	if jointType == Vehicle.JOINTTYPE_TRAILER or jointType == Vehicle.JOINTTYPE_TRAILERLOW then
		if self.activeAttacher ~= nil then
			if jointIndex == self.topTrailerAttacher.attacherIndex and self.bValidate then
				self.bValidate = false;
				return true;
			elseif jointIndex == self.lowTrailerAttacher.attacherIndex and self.bValidate then
				self.bValidate = false;
				return true;
			end;
		else
			return false;
		end;
	end;
	
    return false;
end;

function BJR_AdjustableAttacher:setNewTranslation(attacherId, yTrans, noEventSend)
	BJR_AdjustableAttacherEvent.sendEvent(self, attacherId, yTrans, noEventSend);	
	
	if attacherId == 1 then
		local x, y, z = getTranslation(self.topTrailerAttacher.index);
		setTranslation(self.topTrailerAttacher.index, x, yTrans, z);
		self.bValidate = true;
	elseif attacherId == 2 then
		local x, y, z = getTranslation(self.lowTrailerAttacher.index);
		setTranslation(self.lowTrailerAttacher.index, x, yTrans, z);
		self.bValidate = true;
	end;
end;

--
-- BJR_AdjustableAttacherEvent
-- Networkevent for BJR_AdjustableAttacher
--
-- @author  	JoXXer, rf928
-- @date  		09/03/13
--
BJR_AdjustableAttacherEvent = {};
BJR_AdjustableAttacherEvent_mt = Class(BJR_AdjustableAttacherEvent, Event);

InitEventClass(BJR_AdjustableAttacherEvent, "BJR_AdjustableAttacherEvent");

function BJR_AdjustableAttacherEvent:emptyNew()
    local self = Event:new(BJR_AdjustableAttacherEvent_mt);
    return self;
end;

function BJR_AdjustableAttacherEvent:new(vehicle, attacherId, yTrans)
    local self = BJR_AdjustableAttacherEvent:emptyNew()
    self.vehicle = vehicle;
	self.attacherId = attacherId;
	self.yTrans = yTrans;
    return self;
end;

function BJR_AdjustableAttacherEvent:readStream(streamId, connection)
    local id = streamReadInt32(streamId);
	self.attacherId = streamReadInt8(streamId);
	self.yTrans = streamReadFloat32(streamId);
    self.vehicle = networkGetObject(id);
    self:run(connection);
end;

function BJR_AdjustableAttacherEvent:writeStream(streamId, connection)
    streamWriteInt32(streamId, networkGetObjectId(self.vehicle));	
	streamWriteInt8(streamId, self.attacherId);
	streamWriteFloat32(streamId, self.yTrans);
end;

function BJR_AdjustableAttacherEvent:run(connection)
	self.vehicle:setNewTranslation(self.attacherId, self.yTrans, true);
end;

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