--
-- BasicGears
--
-- @author:    	Xentro (Marcus@Xentro.se)
-- @website:	www.Xentro.se
-- @history:	v1.0  - 2015-02-15 - Initial implementation
-- 				v1.01 - 2015-08-21 - Small update
-- 
--[[
	<!-- value is the minForwardGearRatio -->
	<BasicGears inputBinding="IMPLEMENT_EXTRA4" inputBinding_down="IMPLEMENT_EXTRA3">
		<gear value="107" />
		<gear value="66" />
	</BasicGears>
]]--

BasicGears = {};

BasicGears.REVERSE = "R";

function BasicGears.prerequisitesPresent(specializations)
	if not SpecializationUtil.hasSpecialization(Motorized, specializations) then print("Warning: Specialization BasicGears needs the specialization Motorized."); end;
	
	return SpecializationUtil.hasSpecialization(Motorized, specializations);
end;

function BasicGears:load(xmlFile)
	self.changeGear = SpecializationUtil.callSpecializationsFunction("changeGear");
	
	BasicGears.loadGearsFromXML(self, xmlFile);
	
	local g = g_currentMission.hudAttachmentOverlay;
	local width, height = getNormalizedScreenValues(g_currentMission.vehicleHudScale * 40, g_currentMission.vehicleHudScale * 40);
	self.gearBaseOverlay = Overlay:new("gearBaseOverlay", Utils.getFilename("gearBaseOverlay.dds", self.baseDirectory .. "shared/"), g.x - 0.1426, g.y + 0.03, width, height);
	
	self.isSelectable = true;
	
	self:changeGear(self.gears["CURRENT"], true);
end;

function BasicGears.loadGearsFromXML(self, xmlFile)
	self.gears = {};
	i = 0;
	while true do
		local key = string.format("vehicle.BasicGears.gear(%d)", i);
		if not hasXMLProperty(xmlFile, key) then break; end;
		
		local value = getXMLFloat(xmlFile, key .. "#value");
		if value ~= nil then
			table.insert(self.gears, value);
		end;
		
		i = i + 1;
	end;
	
	self.gears["MAX"] = i;
	self.gears["CURRENT"] = 1;
	self.gears["INPUTBINDING"] = Utils.getNoNil(InputBinding[getXMLString(xmlFile, "vehicle.BasicGears#inputBinding")], InputBinding.IMPLEMENT_EXTRA4);
	self.gears["RESET_GEAR"] = Utils.getNoNil(getXMLBool(xmlFile, "vehicle.BasicGears#resetGear"), true);
	self.gears["ACTIVE_INPUT"] = Utils.getNoNil(getXMLBool(xmlFile, "vehicle.BasicGears#activeInput"), true);
	local gearDown = getXMLString(xmlFile, "vehicle.BasicGears#inputBinding_down");
	if gearDown ~= nil and InputBinding[gearDown] ~= nil then
		self.gears["INPUTBINDING_DOWN"] = InputBinding[gearDown];
	end;
	
	self.disableDriveControlOnStart = true;
end;

function BasicGears:delete()
	if self.gearBaseOverlay ~= nil then
		self.gearBaseOverlay:delete();
	end;
end;

function BasicGears:readStream(streamId, connection)
	self:changeGear(streamReadInt8(streamId), true)
end;

function BasicGears:writeStream(streamId, connection)
	streamWriteInt8(streamId, self.gears["CURRENT"]);
end;

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

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

function BasicGears:update(dt)
	if self.disableDriveControlOnStart then
		if self.driveControl ~= nil then
			if self.dCdeactivateModule ~= nil then
				self:dCdeactivateModule("gasAndGearLimiter");
			else
				print("BasicGears - Warning: You have an old version of driveControl mod, there will be an conflict with BasicGears!");
			end;
		end;
		
		self.disableDriveControlOnStart = false;
	end;
	
	if self:getIsActive() then
		if self:getIsActiveForInput(self.gears["ACTIVE_INPUT"]) then
			if InputBinding.hasEvent(self.gears["INPUTBINDING"]) then
				self:changeGear(self.gears["CURRENT"] + 1);
			elseif self.gears["INPUTBINDING_DOWN"] ~= nil and InputBinding.hasEvent(self.gears["INPUTBINDING_DOWN"]) then
				self:changeGear(self.gears["CURRENT"] - 1);
			end;
		end;
	end;
end;

function BasicGears:updateTick(dt)
	if self:getIsActive() and self.gears["RESET_GEAR"] then
		if self.axisForward > 0 then
			if self.gears["CURRENT"] > 1 then
				self:changeGear(1, true);
			end;
		end;
	end;
end;

function BasicGears:draw()
	if self:getIsActiveForInput(self.gears["ACTIVE_INPUT"]) then
		g_currentMission:addHelpButtonText(g_i18n:getText("CHANGE_GEAR"), self.gears["INPUTBINDING"]);
		
		if self.gears["INPUTBINDING_DOWN"] ~= nil and g_i18n:hasText("CHANGE_GEAR_DOWN") then
			g_currentMission:addHelpButtonText(g_i18n:getText("CHANGE_GEAR_DOWN"), self.gears["INPUTBINDING_DOWN"]);
		end;
	end;
	
	if self.gearBaseOverlay ~= nil then
		local gear = self.gears["CURRENT"];
		if self.axisForward > 0 then
			gear = BasicGears.REVERSE;
		end;
		
		self.gearBaseOverlay:render();
		
		setTextAlignment(RenderText.ALIGN_CENTER)
		setTextBold(true);
		setTextColor(1, 1, 1, 1);
		renderText(self.gearBaseOverlay.x + 0.0072, self.gearBaseOverlay.y + 0.008, getCorrectTextSize(0.012), tostring(gear));
		setTextAlignment(RenderText.ALIGN_LEFT);
		setTextBold(false);
	end;
end;

function BasicGears:changeGear(gear, noEventSend)
	if self.gears["INPUTBINDING_DOWN"] ~= nil then
		if gear > self.gears["MAX"] then
			gear = self.gears["MAX"];
		elseif gear < 1 then
			gear = 1;
		end;
	else
		if gear > self.gears["MAX"] then
			gear = 1;
		end;
	end;
	
	self.gears["CURRENT"] = gear;
	self.motor.minForwardGearRatio = self.gears[gear];
	self.motor.maxForwardGearRatio = self.gears[gear];
	
	setGearEvent.sendEvent(self, gear, noEventSend);
end;

function BasicGears:developmentReloadFromXML(xmlFile)
	BasicGears.loadGearsFromXML(self, xmlFile);
end;



setGearEvent = {};
setGearEvent_mt = Class(setGearEvent, Event);

InitEventClass(setGearEvent, "setGearEvent");

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

function setGearEvent:new(vehicle, gear)
    local self = setGearEvent:emptyNew();
    self.vehicle = vehicle;
	self.gear = gear;
	
    return self;
end;

function setGearEvent:readStream(streamId, connection)
    local vehicle = streamReadInt32(streamId);
    self.vehicle = networkGetObject(vehicle);
	self.gear = streamReadInt8(streamId);
	
    self:run(connection);
end;

function setGearEvent:writeStream(streamId, connection)
    streamWriteInt32(streamId, networkGetObjectId(self.vehicle));
	streamWriteInt8(streamId, self.gear);
end;

function setGearEvent:run(connection)
	self.vehicle:changeGear(self.gear, true);
	
	if not connection:getIsServer() then
		g_server:broadcastEvent(setGearEvent:new(self.vehicle, self.gear), nil, connection, self.vehicle);
	end;
end;

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