--
-- InteractiveMouseMovement
-- Specialization for InteractiveMouseMovement
--
-- @author  	Stefan Biedenstein (Mogli)
-- @version 	v1.0
-- @date  		
-- @history:	v1.0 - Initial version
--
-- free for noncommerical-usage
--

InteractiveMouseMovement = InteractiveControlBase.newSpecialization();

function InteractiveMouseMovement.prerequisitesPresent(specializations)
    return InteractiveControlBase.prerequisitesPresent(specializations) and SpecializationUtil.hasSpecialization(AnimatedVehicle, specializations);
end;

function InteractiveMouseMovement:load(xmlFile)
	local i=0;
	while true do
		local xmlName = string.format("vehicle.interactiveComponents.mouseMovements.mouseMovement(%d)", i);	
		if not hasXMLProperty(xmlFile, xmlName) then
			break;
		end;
		local animationX = getXMLString(xmlFile, xmlName .. "#animNameX");
		local animationY = getXMLString(xmlFile, xmlName .. "#animNameY");
		local event      = getXMLString(xmlFile, xmlName .. "#event");
		local setter     = getXMLString(xmlFile, xmlName .. "#setFunction");
		local getter     = getXMLString(xmlFile, xmlName .. "#getFunction");
		
		local mouseMovement = MouseMovement:new(self, xmlFile, xmlName, animationX, animationY, event, setter, getter);

		table.insert(self.interactiveObjects, mouseMovement);
		i = i + 1;
	end;
end;


--
-- MouseMovement Class
-- Specifies an interactive mouseMovement
--
-- @author  	Stefan Biedenstein (Mogli)
-- @version 	v1.0
--

MouseMovement = {};

function MouseMovement:new(vehicle, xmlFile, xmlName, animationX, animationY, event, setter, getter)

	local MouseMovement_mt = Class(MouseMovement, InteractiveComponentInterface);	
  local instance  = InteractiveComponentInterface:new(vehicle, xmlFile, xmlName, MouseMovement_mt, event, setter, getter);
	instance.animationX = animationX;
	instance.animationY = animationY;
	instance.defaultAnimTimeX  = 0.5 
	instance.defaultAnimTimeY  = 0.5 
	if instance.animationX ~= nil then 
		local t = getXMLFloat(xmlFile, xmlName .. "#animTimeX")
		if t ~= nil then
			local d = instance.vehicle:getAnimationDuration( instance.animationX )
			instance.defaultAnimTimeX = Utils.clamp( 1000*t/d, 0, 1 )
		end
	end
	if instance.animationY ~= nil then 
		local t = getXMLFloat(xmlFile, xmlName .. "#animTimeY")
		if t ~= nil then
			local d = instance.vehicle:getAnimationDuration( instance.animationY )
			instance.defaultAnimTimeY = Utils.clamp( 1000*t/d, 0, 1 )
		end
	end

	instance.initialAnimTimeX = instance.defaultAnimTimeX
	instance.initialAnimTimeY = instance.defaultAnimTimeY
	
	return instance;
end;

function MouseMovement:mouseEvent(posX, posY, isDown, isUp, button)
	InteractiveComponentInterface.mouseEvent(self, posX, posY, isDown, isUp, button);

	if self.isOpen then
		if isUp then
			self.isOpen   = false
			self.lastPosX = nil
			self.lastPosY = nil
		elseif self.lastPosX == nil or self.lastPosY == nil then		
			self.lastPosX = posX
			self.lastPosY = posY
			wrapMousePosition( self.lastPosX, self.lastPosY )
		else
			local animTime = { 0, 0 }
			local setter   = false
			if self.animationX ~= nil and self.initialAnimTimeX == nil then 
				animTime[1] = self.vehicle:getAnimationTime( self.animationX )
				animTime[1] = Utils.clamp( animTime[1] + 3 * Utils.clamp( posX - self.lastPosX, -0.01, 0.01 ), 0, 1 )
				self.vehicle:setAnimationTime( self.animationX, animTime[1], true )
				setter = true
			end
			if self.animationY ~= nil and self.initialAnimTimeY == nil then 
				animTime[2] = self.vehicle:getAnimationTime( self.animationY )
				animTime[2] = Utils.clamp( animTime[2] + 3 * Utils.clamp( posY - self.lastPosY, -0.01, 0.01 ), 0, 1 )
				self.vehicle:setAnimationTime( self.animationY, animTime[2], true )
				setter = true
			end
			if setter and self.vehicle ~= nil and self.setStateFunction ~= nil then
				self.setStateFunction( self.vehicle, animTime )
			end
			wrapMousePosition( self.lastPosX, self.lastPosY )
			InputBinding.accumMouseMovementX = 0
			InputBinding.accumMouseMovementY = 0
		end
	end
	
end;

function MouseMovement:update(dt)	
	InteractiveComponentInterface.update( self, dt )	
	
	local showDebug = false
	if      InteractiveMouseMovement.debugTime ~= nil  
			and ( self.debugTime == nil or self.debugTime < InteractiveMouseMovement.debugTime ) then
		self.debugTime = InteractiveMouseMovement.debugTime
		showDebug = true
	end
	
	if self.animationX ~= nil and self.initialAnimTimeX ~= nil then
		self.vehicle:stopAnimation( self.animationX )
		self.vehicle:setAnimationTime( self.animationX, 0, true )
		self.vehicle:setAnimationTime( self.animationX, 1, true )
		self.vehicle:setAnimationTime( self.animationX, Utils.clamp( self.initialAnimTimeX, 0, 1 ), true )
		self.initialAnimTimeX = nil
	end
	
	if self.animationY ~= nil and self.initialAnimTimeY ~= nil then
		self.vehicle:stopAnimation( self.animationY )
		self.vehicle:setAnimationTime( self.animationY, 0, true )
		self.vehicle:setAnimationTime( self.animationY, 1, true )
		self.vehicle:setAnimationTime( self.animationY, Utils.clamp( self.initialAnimTimeY, 0, 1 ), true )
		self.initialAnimTimeY = nil
	end

	if      not ( self.isOpen ) 
			and self.vehicle          ~= nil 
			and self.getStateFunction ~= nil then
		local animTime = self.getStateFunction( self.vehicle )
		if self.animationX ~= nil then 
			self.vehicle:setAnimationTime( self.animationX, animTime[1], true )
		end
		if self.animationY ~= nil then 
			self.vehicle:setAnimationTime( self.animationY, animTime[2], true )
		end
	end
	
	if showDebug then
		MouseMovement.showDebug( self )
	end
end

--addConsoleCommand("icmDebug", "Debug InteractiveMouseMovement.", "icmDebug", InteractiveMouseMovement);
--function InteractiveMouseMovement:icmDebug()
--	InteractiveMouseMovement.debugTime = g_currentMission.time
--end
--function MouseMovement:showDebug()
--	for _,a in pairs({ self.animationX, self.animationY }) do
--		if a ~= nil then
--			local t1 = self.vehicle:getRealAnimationTime(a)
--			local t2 = self.vehicle:getAnimationTime(a)
--			print("==================================================")
--			print(string.format("%s: %0.3f / %3.0f%%", a, t1*0.001, t2*100 ))
--			print("--------------------------------------------------")
--			local animation = self.vehicle.animations[a]
--			for _,part in pairs( animation.parts ) do
--				if part.node ~= nil then						
--					local f = 0
--					
--					if     t1 <= part.startTime then
--						f = 0
--					elseif t1 >= part.startTime + part.duration then
--						f = 1
--					elseif part.duration > 0 then
--						f = ( t1 - part.startTime ) / part.duration 
--					end
--					
--					if part.endRot ~= nil then
--						local xd = part.endRot[1] - part.startRot[1]
--						local yd = part.endRot[2] - part.startRot[2]
--						local zd = part.endRot[3] - part.startRot[3]
--						
--						local x0 = part.startRot[1] + f * xd
--						local y0 = part.startRot[2] + f * yd
--						local z0 = part.startRot[3] + f * zd
--							
--						local x,y,z = getRotation( part.node )
--					
--						print(string.format("Rotation of %s (%3.0f%%): %3.0f %3.0f %3.0f / %3.0f %3.0f %3.0f", getName( part.node ), f*100, math.deg(x), math.deg(y), math.deg(z), math.deg(x0), math.deg(y0), math.deg(z0) ))
--
--						local f2 = -1
--						if math.abs( xd ) >= math.abs( yd ) and math.abs( xd ) >= math.abs( zd ) then
--							f2 = ( x - part.startRot[1] ) / xd
--						elseif math.abs( yd ) >= math.abs( zd ) then
--							f2 = ( y - part.startRot[2] ) / yd
--						else
--							f2 = ( z - part.startRot[3] ) / zd
--						end
--						x = part.startRot[1]
--						y = part.startRot[2]
--						z = part.startRot[3]
--						print(string.format("%3.0f %3.0f %3.0f / %3.0f %3.0f %3.0f => %3.0f%%", math.deg(x), math.deg(y), math.deg(z), math.deg(xd), math.deg(yd), math.deg(zd), f2*100 ))
--					end
--					if part.endTrans ~= nil then							
--						local x0 = part.startTrans[1] + f * ( part.endTrans[1] - part.startTrans[1] )
--						local y0 = part.startTrans[2] + f * ( part.endTrans[2] - part.startTrans[2] )
--						local z0 = part.startTrans[3] + f * ( part.endTrans[3] - part.startTrans[3] )
--					
--						local x,y,z = getTranslation( part.node )
--						print(string.format("Translation of %s (%3.0f%%): %0.3f %0.3f %0.3f / %0.3f %0.3f %0.3f", getName( part.node ), f*100, x, y, z, x0, y0, z0 ))
--					end
--				end
--			end
--		end
--	end
--	print("==================================================")
--end

function MouseMovement:getSaveAttributes()
	local attributes = ""
	local curAnimTime
	if self.animationX ~= nil then 
		curAnimTime = Utils.clamp(self.vehicle:getAnimationTime(self.animationX), 0, 1)
		if self.defaultAnimTimeX == nil or math.abs( curAnimTime - self.defaultAnimTimeX ) > 1E-3 then
			attributes = attributes .. " animationTimeX=\""..tostring(curAnimTime).."\""
		end
	end
	if self.animationY ~= nil then 
		curAnimTime = Utils.clamp(self.vehicle:getAnimationTime(self.animationY), 0, 1)
		if self.defaultAnimTimeY == nil or math.abs( curAnimTime - self.defaultAnimTimeY ) > 1E-3 then
			attributes = attributes .. " animationTimeY=\""..tostring(curAnimTime).."\""
		end
	end
	return attributes
end

function MouseMovement:setSaveAttributes(xmlFile, xmlName)
	self.initialAnimTimeX = Utils.getNoNil( getXMLFloat(xmlFile, xmlName .. "#animationTimeX"), self.defaultAnimTimeX )
	self.initialAnimTimeY = Utils.getNoNil( getXMLFloat(xmlFile, xmlName .. "#animationTimeY"), self.defaultAnimTimeY )
end