-- author: rafftnix
-- date: 01.01.2015

-- moveableGates.lua

MoveableGates = {};

function MoveableGates.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(AnimatedVehicle, specializations);
end;

function MoveableGates:load(xmlFile)
	self.moveGate = SpecializationUtil.callSpecializationsFunction("moveGate");
	self.gateControlTriggerCallback = MoveableGates.gateControlTriggerCallback;
	
	self.moveableGates = {}
	local num = 0;
	while true do
		local key = "vehicle.moveableGates.gate("..tostring(num)..")";
		if not hasXMLProperty(xmlFile, key) then
			break;
		end;
		
		local gate = {}
		gate.animationName = getXMLString(xmlFile, key.."#animationName");
		gate.axisName = getXMLString(xmlFile, key.."#axisName");
		gate.helpPanelTextName = getXMLString(xmlFile, key.."#helpPanelTextName");
		gate.axisIndex = InputBinding[gate.axisName];
		gate.iconFilename = Utils.getFilename(getXMLString(xmlFile, key.."#iconFile"), self.baseDirectory);
		g_mouseControlsHelp:addIconFilename(gate.iconFilename);
		gate.speedFactor = Utils.getNoNil(getXMLFloat(xmlFile, key.."#speedFactor"), 1);
		gate.mouseSpeedFactor = Utils.getNoNil(getXMLFloat(xmlFile, key.."#mouseSpeedFactor"), 1);
		if getXMLString(xmlFile, key.."#steeringStickIndex") ~= nil then
			gate.steeringStick = Utils.indexToObject(self.components, getXMLString(xmlFile, key.."#steeringStickIndex"));
			gate.steeringStickAmplitude = math.rad(Utils.getNoNil(getXMLFloat(xmlFile, key.."#steeringStickAmplitude"), 15));
			_, _, gate.steeringStickRotZBackup = getRotation(gate.steeringStick);
		end;
		
		local action = InputBinding.actions[gate.axisIndex];
		gate.helpText = g_i18n:getText(gate.helpPanelTextName).." "..KeyboardHelper.getKeyNames(action.keys1).." / "..KeyboardHelper.getKeyNames(action.keys2);
		
		table.insert(self.moveableGates, gate);
		num = num + 1;
	end;
	self.gateControlTrigger = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.moveableGates#controlTriggerIndex"));
	addTrigger(self.gateControlTrigger, "gateControlTriggerCallback", self);
	self.playerIsInGateControlTrigger = false;
end;

function MoveableGates:delete()
	removeTrigger(self.gateControlTrigger);
end;

function MoveableGates:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)
	local gateTimesStr = getXMLString(xmlFile, key.."#gateTimes");
	if gateTimesStr ~= nil then
		local gateTimes = Utils.splitString(" ", gateTimesStr);
		for a=1, table.getn(self.moveableGates) do
			local gate = self.moveableGates[a];
			local animTime = tonumber(gateTimes[a]);
			self:moveGate(a, animTime);
		end;
	end;
	return BaseMission.VEHICLE_LOAD_OK;
end;

function MoveableGates:getSaveAttributesAndNodes(nodeIdent)
	local attributes = 'gateTimes="';
	for a=1, table.getn(self.moveableGates) do
		local gate = self.moveableGates[a];
		local animTime = self:getAnimationTime(gate.animationName);
		attributes = attributes..tostring(animTime).." ";
	end;
	attributes = attributes..'"';
	return attributes, "";
end;

function MoveableGates:readStream(streamId, connection)
	for a=1, table.getn(self.moveableGates) do
		local gate = self.moveableGates[a];
		local animTime = streamReadFloat32(streamId);
		self:moveGate(a, animTime, true);
	end;
end;

function MoveableGates:writeStream(streamId, connection)
	for a=1, table.getn(self.moveableGates) do
		local gate = self.moveableGates[a];
		local animTime = self:getAnimationTime(gate.animationName);
		streamWriteFloat32(streamId, animTime);
	end;
end;

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

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

function MoveableGates:update(dt)
	local gatesMoved = false;
	if g_currentMission.player ~= nil and g_currentMission.player.isEntered then
		local px, py, pz = getWorldTranslation(g_currentMission.player.rootNode);
		local tx, ty, tz = getWorldTranslation(self.gateControlTrigger);
	
		if self.playerIsInGateControlTrigger and self.attacherVehicle ~= nil and Utils.vector3Length(px-tx, py-ty, pz-tz) < 5 then
			for a=1, table.getn(self.moveableGates) do
				local gate = self.moveableGates[a];
				local move, axisType = InputBinding.getInputAxis(gate.axisIndex);

				local steeringStickAmplitude = 0;
				if gate.steeringStick == nil then
					steeringStickAmplitude = nil;
				end;
				if move ~= 0 then
					gatesMoved = true;
					
					local speed = dt*0.001;
					if axisType == InputBinding.INPUTTYPE_MOUSE_AXIS then
						speed = speed * move * gate.speedFactor;
					else
						speed = speed * move * gate.mouseSpeedFactor;
					end;
					
					local animTime = self:getAnimationTime(gate.animationName);
					self:moveGate(a, animTime + speed);
					
					g_mouseControlsHelp:setIconFilename("", gate.iconFilename);
					
					if steeringStickAmplitude ~= nil then
						if move > 0 then
							steeringStickAmplitude = gate.steeringStickAmplitude;
						else
							steeringStickAmplitude = 0-gate.steeringStickAmplitude;
						end;
					end;
				elseif Input.isMouseButtonPressed(Input.MOUSE_BUTTON_LEFT) or Input.isMouseButtonPressed(Input.MOUSE_BUTTON_RIGHT) then
					gatesMoved = true;
					
					if steeringStickAmplitude ~= nil then
						steeringStickAmplitude = 0;
					end;
				else
					if steeringStickAmplitude ~= nil then
						steeringStickAmplitude = 0;
					end;
				end;
				
				if gate.steeringStick ~= nil then
					setRotation(gate.steeringStick, 0, 0, gate.steeringStickRotZBackup + steeringStickAmplitude);
				end;
				
				if self.playerIsInGateControlTrigger then
					g_currentMission:addExtraPrintText(gate.helpText);
				end;
			end;
		end;
        --g_currentMission:setShowHasMouseButtonInput(true);	
	end;
	
	-- no move of the cam while using mouse / gamepad
	if gatesMoved then
		g_currentMission.isPlayerFrozen = true;
		g_currentMission.controlPlayer = false;
		g_currentMission.isPlayerFrozenChangedByMoveableGates = true;
	elseif g_currentMission.isPlayerFrozenChangedByMoveableGates then
		g_currentMission.isPlayerFrozen = false;
		g_currentMission.controlPlayer = true;
		g_currentMission.isPlayerFrozenChangedByMoveableGates = false;
	end;
end;

function MoveableGates:updateTick(dt)
end;

function MoveableGates:draw()
end;

function MoveableGates:gateControlTriggerCallback(triggerId, otherId, onEnter, onLeave, onStay, otherShapeId)
	if g_currentMission.player ~= nil then
		if g_currentMission.player.rootNode == otherId and g_currentMission.player.isEntered then
			if onEnter then
				self.playerIsInGateControlTrigger = true;
			elseif onLeave then
				self.playerIsInGateControlTrigger = false;
			end;
		end;
	end;
end;

function MoveableGates:moveGate(gateIndex, animTime, noEventSend)
	local gate = self.moveableGates[gateIndex];
	self:setAnimationTime(gate.animationName, animTime, true);
	for a=1, table.getn(self.movingParts) do
		Cylindered.updateMovingPart(self, self.movingParts[a], false);
	end;
	
	if not noEventSend then
		MoveGateEvent.sendEvent(self, gateIndex, animTime, noEventSend);
	end;
end;