--
-- 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(savegame)
    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