--
-- Beifahrer.lua
--
-- @author  Alex2009(www.Alex2009.de)
-- @basis of JoXXer
-- @date  26/11/11
--

Beifahrer = {};

function Beifahrer.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(Steerable, specializations);
end;

function Beifahrer:load(xmlFile)
	self.setBeifahrer = SpecializationUtil.callSpecializationsFunction("setBeifahrer");
    self.BeifahrerFarmerNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.Beifahrer.BeifahrerNode#index"));
	self.BeifahrerNicknameRenderNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.Beifahrer.NicknameNode#index"));
	self.BeifahrerNicknameRenderNodeOffset = {0,0,0};
	self.BeifahrerPlayer = nil;
	self.BeifahrerName = "";
	self.BeifahrerCameras = {};
	local BeifahrerCameraName = string.format("vehicle.Beifahrer.Kamera");
	local BeifahrerCamera = VehicleCamera:new(self);
	if BeifahrerCamera:loadFromXML(xmlFile, BeifahrerCameraName) then
		table.insert(self.BeifahrerCameras, BeifahrerCamera);
    end;
	self.inRangeOfVehicle = false;
	self.isChatting = false;
    self.PlayerAttach = {};
    setVisibility(self.BeifahrerFarmerNode,false);
end;

function Beifahrer:delete()
	for _, BeifahrerCamera in ipairs(self.BeifahrerCameras) do
        BeifahrerCamera:delete();
    end;
end;

function Beifahrer:readStream(streamId, connection)
	local BeifahrerPlayerId = streamReadInt32(streamId);
	self.BeifahrerName = streamReadString(streamId);

	if BeifahrerPlayerId ~= -1 then
		self.BeifahrerPlayer = networkGetObject(BeifahrerPlayerId);
	end;
end;

function Beifahrer:writeStream(streamId, connection)
	if self.BeifahrerPlayer ~= nil then
		streamWriteInt32(streamId, networkGetObjectId(self.BeifahrerPlayer));
	else
		streamWriteInt32(streamId, -1);
	end;
	streamWriteString(streamId, self.BeifahrerName);
end;

function Beifahrer:readUpdateStream(streamId, timestamp, connection)

end;

function Beifahrer:writeUpdateStream(streamId, connection, dirtyMask)

end;

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

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

function Beifahrer:update(dt)
	if self.BeifahrerPlayer ~= nil then
		if not self.BeifahrerPlayer.isControlled and not self.BeifahrerPlayer.isEntered then
            if self.BeifahrerPlayer == g_currentMission.player then
                g_currentMission.isPlayerFrozen = false;
            end;
			self:setBeifahrer("ExitedToOtherVehicle", nil);
            return;
		end;
	end;
	if self.inRangeOfVehicle and self.BeifahrerPlayer == nil and self.isControlled and g_settingsNickname ~= self.controllerName then
		g_currentMission:addHelpButtonText(string.format(g_i18n:getText("Beifahrer_Enter"), self.typeDesc), InputBinding.ENTER);
		if InputBinding.hasEvent(InputBinding.ENTER) then   
			self:setBeifahrer(g_settingsNickname, g_currentMission.player);
            g_currentMission.hasSpecialCamera = true;
			self.BeifahrerCameras[1]:onActivate();
            g_currentMission.hasSpecialCamera = true;
            self.BeifahrerPlayer.rotX = 0;
            self.BeifahrerPlayer.rotY = 180;
            return;
		end;
	end;
	if self.BeifahrerPlayer ~= nil then
        if self.BeifahrerPlayer ~= nil then
			if g_currentMission:getIsServer() then
				if g_currentMission.connectionsToPlayer[self.BeifahrerPlayer.creatorConnection] == nil then
					self:setBeifahrer("Disconnected", nil);
                    return;
				end;
			end;
		end;
		self.BeifahrerCameras[1]:update(dt);
		if self.BeifahrerName == g_settingsNickname then
			if InputBinding.hasEvent(InputBinding.CHAT) and not self.isChatting then
				self.isChatting = true;
			end;
			if InputBinding.hasEvent(InputBinding.MENU_ACCEPT) and self.isChatting then
				self.isChatting = false;
			end;
            local inputZ = InputBinding.getDigitalInputAxis(InputBinding.AXIS_LOOK_LEFTRIGHT_PLAYER)
            local inputW = InputBinding.getDigitalInputAxis(InputBinding.AXIS_LOOK_UPDOWN_PLAYER)
            if InputBinding.isAxisZero(inputZ) then
              inputZ = InputBinding.getAnalogInputAxis(InputBinding.AXIS_LOOK_LEFTRIGHT_PLAYER)
            end
            if InputBinding.isAxisZero(inputW) then
              inputW = InputBinding.getAnalogInputAxis(InputBinding.AXIS_LOOK_UPDOWN_PLAYER)
            end
            local rotSpeed = 0.001 * dt
            self.BeifahrerPlayer.rotX = self.BeifahrerPlayer.rotX - rotSpeed * inputW
            self.BeifahrerPlayer.rotY = self.BeifahrerPlayer.rotY - rotSpeed * inputZ
            self.BeifahrerPlayer.rotX = math.min(1.2, math.max(-1.5, self.BeifahrerPlayer.rotX))
            setRotation(self.BeifahrerPlayer.cameraId, self.BeifahrerPlayer.rotX, 0, 0)
            setRotation(self.BeifahrerPlayer.graphicsRootNode, 0, self.BeifahrerPlayer.rotY, 0)
            if self.BeifahrerPlayer ~= nil and self.BeifahrerPlayer.cameraId ~= nil and self.BeifahrerPlayer.graphicsRootNode ~= nil then
                local pcx, pcy, pcz = getRotation(self.BeifahrerPlayer.cameraId);
                local prx, pry, prz = getRotation(self.BeifahrerPlayer.graphicsRootNode);
                setRotation(self.BeifahrerCameras[1].cameraNode, pcx, (pry+180), 0);
            end;
			g_currentMission:addHelpButtonText(string.format(g_i18n:getText("Beifahrer_Exit"), self.typeDesc), InputBinding.ENTER);
            if InputBinding.hasEvent(InputBinding.ENTER) and not self.isChatting then
                g_currentMission.hasSpecialCamera = false;
				self.BeifahrerCameras[1]:onDeactivate();
                g_currentMission.hasSpecialCamera = false;
				setCamera(self.BeifahrerPlayer.cameraId);
                g_currentMission.hasSpecialCamera = false;
                g_currentMission.isPlayerFrozen = false;
				self:setBeifahrer("Exited", nil);
			end;
        else
            setVisibility(self.BeifahrerFarmerNode,true);
		end;
	end;
end;

function Beifahrer:updateTick(dt)
	if g_currentMission.player ~= nil then
		local nearestDistance = 4.0;
		local px, py, pz = getWorldTranslation(self.rootNode);
		local vx, vy, vz = getWorldTranslation(g_currentMission.player.rootNode);
		local distance = Utils.vector3Length(px-vx, py-vy, pz-vz);
		if distance < nearestDistance then
			self.inRangeOfVehicle = true;
		else
			self.inRangeOfVehicle = false;
		end;
	end;
end;

function Beifahrer:draw()
	if g_settingsNickname ~= nil then
		if self.BeifahrerName ~= g_settingsNickname and self.isControlled and self.BeifahrerPlayer ~= nil and g_gui.currentGui == nil then
			local x,y,z = getWorldTranslation(self.BeifahrerNicknameRenderNode);
			local x1,y1,z1 = getWorldTranslation(getCamera())
			local distSq = Utils.vector3LengthSq(x-x1,y-y1,z-z1);
			if distSq <= 100*100 then
				x = x + self.BeifahrerNicknameRenderNodeOffset[1];
				y = y + self.BeifahrerNicknameRenderNodeOffset[2];
				z = z + self.BeifahrerNicknameRenderNodeOffset[3];
				local sx,sy,sz = project(x,y,z);
				if sz <= 1 then
					setTextAlignment(RenderText.ALIGN_CENTER);
					setTextBold(false);
					setTextColor(0.0, 0.0, 0.0, 0.75);
					renderText(sx, sy-0.0015, 0.02, self.BeifahrerName);

					setTextColor(0.5, 1.0, 0.5, 1.0);
					renderText(sx, sy, 0.02, self.BeifahrerName);

					setTextAlignment(RenderText.ALIGN_LEFT);
				end;
			end;
		end;
	end;
end;

function Beifahrer:onLeave()
end;

function Beifahrer:onEnter()
end;

function Beifahrer:getXMLStatsAttributes()
    return string.format("beifahrer=\"%s\"",Utils.encodeToHTML(tostring(self.BeifahrerName)));
end

function Beifahrer:setBeifahrer(BeifahrerName, BeifahrerPlayer, noEventSend)
	SetBeifahrerEvent.sendEvent(self, BeifahrerName, BeifahrerPlayer, noEventSend);
	if BeifahrerPlayer ~= nil then
        local x,y,z = getWorldTranslation(self.BeifahrerFarmerNode);
        BeifahrerPlayer:moveToAbsolute(x,(y-500),z);
		setTranslation(BeifahrerPlayer.rootNode,x,(y-500),z);
        if self.HoldAtVehiclePlayer == g_currentMission.player then
            g_currentMission.isPlayerFrozen = true;
        end;
		self.BeifahrerName = BeifahrerName;                           
	elseif BeifahrerName == "Exited" then
        self.BeifahrerPlayer:moveToExitPoint(self);
		self.BeifahrerName = "";
        setVisibility(self.BeifahrerFarmerNode,false);
	else
		self.BeifahrerName = "";
        setVisibility(self.BeifahrerFarmerNode,false);
	end;

	self.BeifahrerPlayer = BeifahrerPlayer;
end;

SetBeifahrerEvent = {};
SetBeifahrerEvent_mt = Class(SetBeifahrerEvent, Event);

InitEventClass(SetBeifahrerEvent, "SetBeifahrerEvent");

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

function SetBeifahrerEvent:new(vehicle, BeifahrerName, BeifahrerPlayer)
    local self = SetBeifahrerEvent:emptyNew()
    self.vehicle = vehicle;
	self.BeifahrerName = BeifahrerName;
	self.BeifahrerPlayer = BeifahrerPlayer;
    return self;
end;

function SetBeifahrerEvent:readStream(streamId, connection)
    local id = streamReadInt32(streamId);
	local BeifahrerPlayerId = streamReadInt32(streamId);
	self.BeifahrerName = streamReadString(streamId);

    self.vehicle = networkGetObject(id);
	self.BeifahrerPlayer = networkGetObject(BeifahrerPlayerId);
    self:run(connection);
end;

function SetBeifahrerEvent:writeStream(streamId, connection)
    streamWriteInt32(streamId, networkGetObjectId(self.vehicle));
	streamWriteInt32(streamId, networkGetObjectId(self.BeifahrerPlayer));
	streamWriteString(streamId, self.BeifahrerName);
end;

function SetBeifahrerEvent:run(connection)
	self.vehicle:setBeifahrer(self.BeifahrerName, self.BeifahrerPlayer, true);
    if not connection:getIsServer() then
        g_server:broadcastEvent(SetBeifahrerEvent:new(self.vehicle, self.BeifahrerName, self.BeifahrerPlayer), nil, connection, self.vehicle);
    end;
end;

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