--[[
/*******************************************************************************\
*                                                                               *
* Levitator.lua                                                                 *
*                                                                               *
*********************************************************************************
* Licensed under the MIT or X11 License                                         *
*                                                                               *
* Copyright (c) 2016 Eisbearg                                                   *
*                                                                               *
* Permission is hereby granted, free of charge, to any person obtaining a copy  *
* of this software and associated documentation files (the "Software"), to deal *
* in the Software without restriction, including without limitation the rights  *
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell     *
* copies of the Software, and to permit persons to whom the Software is         *
* furnished to do so, subject to the following conditions:                      *
*                                                                               *
* The above copyright notice and this permission notice shall be included in    *
* all copies or substantial portions of the Software.                           *
*                                                                               *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR    *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,      *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE   *
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER        *
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, *
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN     *
* THE SOFTWARE.                                                                 *
\*******************************************************************************/
--]]




Levitator = {};

Levitator._NAME			= "Levitator"
Levitator._COPYRIGHT	= "Copyright (C) 2016 Eisbearg"
Levitator._DESCRIPTION	= "Specialization that will levitate vehicles"
Levitator._VERSION		= "1.2.0"




 source(Utils.getFilename("inspect.lua", g_currentModDirectory.."scripts/"))




function Levitator.prerequisitesPresent(specializations)
    return true;
end;


function Levitator:load(xmlFile)
	self.toggleLevitator = SpecializationUtil.callSpecializationsFunction("toggleLevitator");
	self.Levitator = {};

	self.isSelectable = true;

	local name = getXMLString(xmlFile, "vehicle.name");
	if name == nil then name = getXMLString(xmlFile, "vehicle.name.en"); end;
	if name == nil then name = getXMLString(xmlFile, "vehicle.name.de"); end;
	if name == nil then name = getXMLString(xmlFile, "vehicle.name.es"); end;
	if name == nil then name = getXMLString(xmlFile, "vehicle.name.fr"); end;
	if name == nil then name = getXMLString(xmlFile, "vehicle.name.pt"); end;
	if name == nil then name = getXMLString(xmlFile, "vehicle.name.ru"); end;
	if name == nil then name = "UnknownVehicle"; end;
	print("--- inserting "..Levitator._NAME.." in vehicle "..name);

	self.Levitator.id = Levitator._NAME;
	self.Levitator.name = name;
	self.Levitator.move = false;
	self.Levitator.active = false;
	self.Levitator.downForce = 0;
	self.Levitator.yForce = 0;
	self.Levitator.pitch = 0;
	self.Levitator.dt = 0;
--	self.Levitator.soundRotorRun = Utils.loadSample(xmlFile, {}, "vehicle.Levitator.soundRotorRun", nil, self.baseDirectory);
--	self.Levitator.sounding = false;
	
	self.lastDigitalSide = 0;
	
		self.workAreaPositions = {};
	for k,c in pairs (self.workAreas) do
		local xs,ys,zs = getTranslation(c.start);
		local xw,yw,zw = getTranslation(c.width);
		local xh,yh,zh = getTranslation(c.height);
		local cap = {};
		cap.start = {xs,ys,zs};
		cap.width = {xw,yw,zw};
		cap.height = {xh,yh,zh};
		table.insert(self.workAreaPositions, cap);
	end;

        self.tipRotationNodes = Utils.loadRotationNodes(xmlFile, {}, "vehicle.tipRotationNodes.tipRotationNode", "levitator", self.components);

	self.wiper = false;
 self.wiperAnimation = getXMLString(xmlFile, "vehicle.wiperAnimation#animationName");
 self.wiperAnimationSpeed = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.wiperAnimation#speed"), 1);
	self.wiper2 = false;
 self.wiper2Animation = getXMLString(xmlFile, "vehicle.wiper2Animation#animationName");
 self.wiper2AnimationSpeed = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.wiper2Animation#speed"), 1);

    self.pipeGrainParticleSystem = {};
    self.pipeGrainParticleSystemindex = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.pipeGrainParticleSystem#index"));
    Utils.loadParticleSystem(xmlFile, self.pipeGrainParticleSystem, "vehicle.pipeGrainParticleSystem", self.pipeGrainParticleSystemindex, false, nil, self.baseDirectory);
    self.pipeGrainParticleSystem2 = {};
    self.pipeGrainParticleSystem2index = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.pipeGrainParticleSystem2#index"));
    Utils.loadParticleSystem(xmlFile, self.pipeGrainParticleSystem2, "vehicle.pipeGrainParticleSystem2", self.pipeGrainParticleSystem2index, false, nil, self.baseDirectory);
end;


function Levitator:delete()
Utils.deleteParticleSystem(self.pipeGrainParticleSystem); 
Utils.deleteParticleSystem(self.pipeGrainParticleSystem2); 
end;


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


function Levitator:keyEvent(unicode, sym, modifier, isDown)

end;


function Levitator:activateFlightMode()
	setLinearDamping(self.components[1].node, 0.18);
	setAngularDamping(self.components[1].node, 0.29);
	self.Levitator.downForce = self:getTotalMass(true, false) * 9.81;
	self.Levitator.yForce = self.Levitator.downForce;
	self.cruiseControl.average = (self.cruiseControl.minSpeed + self.cruiseControl.maxSpeed);
	self.setCruiseControlMaxSpeed(self, self.cruiseControl.average);
--	Utils.playSample(self.Levitator.soundRotorRun, 0, 0, nil);
end;


function Levitator:deactivateFlightMode()
	setLinearDamping(self.components[1].node, 0.0);
	setAngularDamping(self.components[1].node, 0.01);
	self.Levitator.downForce = self:getTotalMass(true, false) * 9.81;
	self.Levitator.yForce = self.Levitator.downForce;
	self.cruiseControl.average = (self.cruiseControl.minSpeed + self.cruiseControl.maxSpeed);
	self.setCruiseControlMaxSpeed(self, self.cruiseControl.average);
--	Utils.stopSample(self.Levitator.soundRotorRun);
end;


function Levitator:update(dt)
    if self.isClient then
        Utils.updateRotationNodes(self, self.tipRotationNodes, dt, self.isMotorStarted);
		end

			local altAboveGround, altAboveNN = Levitator:getAltitude(self.components[1].node);
	                               self.altAboveGround = altAboveGround;
	                               if self.isMotorStarted and self.altAboveGround < 5 then
					Utils.setEmittingState(self.pipeGrainParticleSystem, true);
				else
			  	Utils.setEmittingState(self.pipeGrainParticleSystem, false);
			end;
                                                          if self.isMotorStarted and self.altAboveGround < 12 then
					Utils.setEmittingState(self.pipeGrainParticleSystem2, true);
				else
			  	Utils.setEmittingState(self.pipeGrainParticleSystem2, false);
			end;
	   
if self.isMotorStarted and (g_currentMission.environment.dayTime > 22*3600000 or g_currentMission.environment.dayTime < 6*3600000) then
				self.wiper2 = true;
else
				self.wiper2 = false;
               end;
			   
if self.wiper2Animation ~= nil and self.playAnimation ~= nil then
	if self.wiper2 then
	        self:playAnimation(self.wiper2Animation, self.wiper2AnimationSpeed, self:getAnimationTime(self.wiper2Animation), true);
                 else
	        self:playAnimation(self.wiper2Animation, -self.wiper2AnimationSpeed, self:getAnimationTime(self.wiper2Animation), true);
              end;
       end;
			   
if self.wiperAnimation ~= nil and self.playAnimation ~= nil then
	if self.wiper then
	        self:playAnimation(self.wiperAnimation, self.wiperAnimationSpeed, self:getAnimationTime(self.wiperAnimation), true);
                 else
	        self:playAnimation(self.wiperAnimation, -self.wiperAnimationSpeed, self:getAnimationTime(self.wiperAnimation), true);
              end;
       end;

	if self.isMotorStarted and Utils.isSamplePlaying(self.sampleMotor) then
			if self.Levitator.active == false then Levitator.activateFlightMode(self); end
			self.Levitator.active = true;
				self.wiper = true;
		else
			if self.Levitator.active == true then Levitator.deactivateFlightMode(self); end
			self.Levitator.active = false;
				self.wiper = false;
		end;

	if not self.Levitator.active then return end;
	
	Levitator.updateMovement(self, dt);
	
	setLinearDamping(self.components[1].node, 0.18);
	setAngularDamping(self.components[1].node, 0.33);
	
	local dX,dY,dZ = localDirectionToWorld(self.components[1].node, 1, 0, 0);
	local sinDir = dX / 1;
	local cosDir = dZ / -1;

self.sd = self.sd

       if self.isTurnedOn then
	self.sd = 10;
	        else
	self.sd = 22;
	        end;

	local zSteer = self.sd * self.axisForward * -1;
--	local zSteer = 22 * self.axisForward * -1;
	local xForce = zSteer * cosDir;
	local zForce = zSteer * sinDir;
	if Input.isMouseButtonPressed(Input.MOUSE_BUTTON_LEFT) or Input.isMouseButtonPressed(Input.MOUSE_BUTTON_RIGHT) then
		if Input.isMouseButtonPressed(Input.MOUSE_BUTTON_LEFT) then
			self.Levitator.pitch = self.Levitator.pitch + 0.16
			if self.Levitator.pitch > self.Levitator.downForce / 2 then self.Levitator.pitch = self.Levitator.downForce / 2 end;
		end;
		if Input.isMouseButtonPressed(Input.MOUSE_BUTTON_RIGHT) then
			self.Levitator.pitch = self.Levitator.pitch - 0.066
			if self.Levitator.pitch < self.Levitator.downForce / -4 then self.Levitator.pitch = self.Levitator.downForce / -4 end;
		end;
	else
		self.Levitator.pitch = 0;
	end
	self.Levitator.yForce = self.Levitator.pitch + self.Levitator.downForce;
	addForce(self.components[1].node, xForce, self.Levitator.yForce, zForce, 0, 0.66, -0.00, true);
	
	local yTurnSpeed = 0;
	if self.axisSide > 0.1 or self.axisSide < -0.1 or self.lastDigitalSide > 0.1 or self.lastDigitalSide < -0.1  then
		if self.axisSideIsAnalog then
			yTurnSpeed = self.axisSide * -0.81;
		else
			yTurnSpeed = self.lastDigitalSide * -0.81;
		end;
	end
	
	local AVx, AVy, AVz = getAngularVelocity(self.components[1].node);
	if yTurnSpeed == 0 then
		setAngularVelocity(self.components[1].node, AVx * 0.75, AVy * 0.95, AVz * 0.75);
	else
		setAngularVelocity(self.components[1].node, AVx * 0.75, yTurnSpeed, AVz * 0.75);
	end;
	
	if self:getIsActive() and self.isTurnedOn then
			local altAboveGround = Levitator:getAltitude(self.components[1].node);
		local addw = altAboveGround*20;
		local addh = altAboveGround/5;
		local addz = (altAboveGround/2) + (self.lastSpeed * 3850/50);
		for c=1, table.getn(self.workAreas) do
			local cp = self.workAreaPositions[c];
			local ca = self.workAreas[c];
			setTranslation(ca.start ,  cp.start[1]+ (cp.start[1] *addw/100) , cp.start[2]  , cp.start[3]- addz);
			setTranslation(ca.width ,  cp.width[1]+ (cp.width[1] *addw/100) , cp.width[2]  , cp.width[3]- addz);
			if altAboveGround > 30 then
				setTranslation(ca.height , cp.start[1]+(cp.start[1]*addw/100) , cp.start[2] , cp.start[3] - addz);
			else
				setTranslation(ca.height , cp.height[1]+(cp.height[1]*addw/100) , cp.height[2] , cp.height[3]-addz-addh);
			end;
		end;
	end;
end;


function Levitator:updateTick(dt)
end;


function Levitator:draw()
	if self.isEntered then

		setTextAlignment(RenderText.ALIGN_CENTER);
		setTextColor(1,1,1,1);

		if self.Levitator.active then
			renderText(0.87, 0.29, 0.016, g_i18n:getText("move"));
			renderText(0.87, 0.27, 0.016, string.format(g_i18n:getText("current") .. " %3.4f ", self.Levitator.pitch));
			local altAboveGround, altAboveNN = Levitator:getAltitude(self.components[1].node);
			renderText(0.87, 0.24, 0.016, string.format(g_i18n:getText("ground") .. " %4.2f m", altAboveGround));
			renderText(0.87, 0.22, 0.016, string.format(g_i18n:getText("NN") .. " %4.2f m", altAboveNN));
			local xLV, yLV, zLV = getLinearVelocity(self.components[1].node);
			renderText(0.87, 0.20, 0.016, string.format(g_i18n:getText("verticalVelocity") .. " %4.2f m/s", yLV));
			setTextBold(false);
		end;
	
		setTextAlignment(RenderText.ALIGN_LEFT);
		setTextColor(1,1,1,1);
	end;
			local altAboveGround = Levitator:getAltitude(self.components[1].node);
		if self.isTurnedOn and altAboveGround > 30 then
		g_currentMission:addWarning(g_i18n:getText("helpGrid"), 0.018, 0.033);
	end;
end;


function Levitator:toggleLevitator(state, nes)
end;


function Levitator:readStream(streamId, connection)
end;
		
	
function Levitator:writeStream(streamId, connection)
end;


function Levitator:getMorldDirectionDegree(rootNode)
	local dX,dY,dZ = localDirectionToWorld(rootNode, 0, 0, 1);
	local sinus = dX / 1;
	local cosinus = dZ / 1;
	local direction = math.deg(math.atan2(sinus, cosinus));
	return direction, sinus, cosinus;
end;


function Levitator:getMorldDirectionDegree2(rootNode)
	local dX,dY,dZ = localDirectionToWorld(rootNode, 0, 0, 1);
	local sinus = dX / 1;
	local cosinus = dZ / 1;
	local direction = math.deg(math.atan2(cosinus, sinus));
	return direction, sinus, cosinus;
end;


function Levitator:getMorldDirectionDegree3(rootNode)
	local dX,dY,dZ = localDirectionToWorld(rootNode, 0, 0, -1);
	local sinus = dX / 1;
	local cosinus = dZ / 1;
	local direction = math.deg(math.atan2(cosinus, sinus));
	return direction, sinus, cosinus;
end;


function Levitator:getAltitude(rootNode)
	local terrainHeight = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, getWorldTranslation(rootNode));
	local x, altAboveNN = getWorldTranslation(rootNode);
	local altAboveGround = altAboveNN - terrainHeight;
	if altAboveGround < 0 then altAboveGround = 0.0 end;
	return altAboveGround, altAboveNN, terrainHeight;
end;


function Levitator:getTailForce(rootNode, xSteer)
		
		local dX,dY,dZ = localDirectionToWorld(rootNode, 0, 0, -1);
		local sinDir = dX / 1;
		local cosDir = dZ / 1;
		local xBackward = 10 * sinDir;
		local zBackward = 10 * cosDir;
		
		dX,dY,dZ = localDirectionToWorld(rootNode, 1, 0, 0);
		sinDir = dX / 1;
		cosDir = dZ / 1;
		local xTurnForce = xSteer * sinDir;
		local zTurnForce = xSteer * cosDir;

	return xTurnForce, 0, zTurnForce, xBackward, 0.6, zBackward 
end;


function Levitator:updateMovement(dt)
    if not self.isEntered then return; end
    
    local axisForward = InputBinding.getDigitalInputAxis(InputBinding.AXIS_MOVE_FORWARD_VEHICLE);
    if InputBinding.isAxisZero(axisForward) then
        self.axisForward = InputBinding.getAnalogInputAxis(InputBinding.AXIS_MOVE_FORWARD_VEHICLE)
        if not InputBinding.isAxisZero(self.axisForward) then
            self.axisForwardIsAnalog = true;
        end
        self.lastDigitalForward = 0;
    else
        self.axisForward = Utils.clamp(self.lastDigitalForward + dt/self.axisSmoothTime*axisForward, -1, 1);
        self.axisForwardIsAnalog = false;
        self.lastDigitalForward = self.axisForward;
    end;
        
    self.axisSide = InputBinding.getDigitalInputAxis(InputBinding.AXIS_MOVE_SIDE_VEHICLE);
    if InputBinding.isAxisZero(self.axisSide) then
        self.axisSide = InputBinding.getAnalogInputAxis(InputBinding.AXIS_MOVE_SIDE_VEHICLE)
        if not InputBinding.isAxisZero(self.axisSide) then
            self.axisSideIsAnalog = true;
        end
        self.lastDigitalSide = 0;
    else
        self.axisSide = Utils.clamp(self.lastDigitalSide + dt/self.axisSmoothTime*self.axisSide, -1, 1);
        self.axisSideIsAnalog = false;
        self.lastDigitalSide = self.axisSide;
    end;
        
    if not self:getIsActiveForInput(false) then
        if not self.axisSideIsAnalog then
            self.axisSide = 0;
        end
        if not self.axisForwardIsAnalog then
            self.axisForward = 0;
        end
    end
        
--    if self.isMotorStarted and self.motorStartTime <= g_currentMission.time then
--    end;
    
end;

