--
-- InteractiveRocker
-- Specialization for InteractiveRocker
--
-- @author      Stefan Biedenstein
-- @version     v3.0
-- @date          
-- @history:    v1.0 - Initial version
--
-- free for noncommerical-usage
--

InteractiveRocker = InteractiveControlBase.newSpecialization();

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

function InteractiveRocker:load(savegame)
    local i=0;
    while true do
        local xmlName = string.format("vehicle.interactiveComponents.rockers.rocker(%d)", i);    
        local xmlNameUp = xmlName..".up"
        local xmlNameDown = xmlName..".down"
        if not hasXMLProperty(xmlFile, xmlNameUp) or not hasXMLProperty(xmlFile, xmlNameDown) then
            break;
        end;
        local animation    = getXMLString(xmlFile, xmlName .. "#animName");
        local moveTime     = getXMLFloat( xmlFile, xmlName .. "#moveTime");
        local event        = getXMLString(xmlFile, xmlName .. "#event");
        local setter       = getXMLString(xmlFile, xmlName .. "#setFunction");
        local getter       = getXMLString(xmlFile, xmlName .. "#getFunction");
        
    --local animTime     = Utils.getNoNil( getXMLFloat(xmlFile, xmlNameUp .. "#animTime"), 0.5 );
        local animTime     = 0.5
        local t = getXMLFloat(xmlFile, xmlName .. "#animTime")
        if t ~= nil then
            local d  = self:getAnimationDuration( animation )
            animTime = Utils.clamp( 1000*t/d, 0, 1 )
        end
        local animUp       = getXMLString(xmlFile, xmlNameUp .. "#animName");
        local animDown     = getXMLString(xmlFile, xmlNameDown .. "#animName");
        local onMessageId  = getXMLString(xmlFile, xmlName .. "#onMessage");
        local offMessageId = getXMLString(xmlFile, xmlName .. "#offMessage");

        local rockerParent = RockerParent:new(self, animation, animTime, moveTime, nil, event, setter, getter )
        local rockerUp     = Rocker:new(self, xmlFile, xmlNameUp, rockerParent, animUp, true );
        local rockerDown   = Rocker:new(self, xmlFile, xmlNameDown, rockerParent, animDown, false );
        
        if onMessageId  ~= nil then
            rockerUp.onMessage    = g_i18n:getText( onMessageId  )
            rockerDown.onMessage  = rockerUp.onMessage
    end
        if offMessageId ~= nil then
            rockerUp.offMessage   = g_i18n:getText( offMessageId )    
            rockerDown.offMessage = rockerUp.offMessage
        end
        
        rockerUp.saveAttributes   = Utils.getNoNil(getXMLBool(xmlFile, xmlName .. "#saveAttributes"), true);
        rockerDown.saveAttributes = false
        
        table.insert(self.interactiveObjects, rockerUp);
        table.insert(self.interactiveObjects, rockerDown);
        i = i + 1;
    end;
end;


--
-- Rocker Class
-- Specifies an interactive rocker
--
-- SFM-Modding
-- @author  Manuel Leithner
-- @date  26/12/09
--

RockerParent = {};
    
function RockerParent:new(vehicle, animation, animTime, moveTime, mt, event, setter, getter )

    local mTable;
    if mt == nil then
        mTable = Class(RockerParent);
    else
        mTable = mt;
    end;
  local instance = {};
  setmetatable(instance, mTable);
    
    instance.vehicle   = vehicle;
    instance.animation = animation;
    instance.moveTime  = moveTime;
    instance.isActive  = true
    instance.defaultAnimTime = Utils.getNoNil( animTime, 0 )
    
    if animation ~= nil and animTime ~= nil then 
        vehicle:setAnimationTime( animation, 0, true )
        vehicle:setAnimationTime( animation, 1, true )
        vehicle:setAnimationTime( animation, animTime, true )
    end

    InteractiveComponentInterface.parseEventSetterGetter( instance, event, setter, getter );
    instance.setStateFunction = InteractiveComponentInterface.getSetter( instance );
    instance.getStateFunction = InteractiveComponentInterface.getGetter( instance );
    
    return instance;
end;

function RockerParent:setActive(isActive)
    self.isActive = isActive;
end

Rocker = {};

function Rocker:new(vehicle, xmlFile, xmlName, parent, animation, increase )

    local Rocker_mt = Class(Rocker, InteractiveComponentInterface);    
  local instance  = InteractiveComponentInterface:new(vehicle, xmlFile, xmlName, Rocker_mt);
    instance.parent    = parent;
    instance.animation = animation;
    instance.increase  = increase;
    
    instance.moveFrame = nil;
    
    if increase then
        parent.up = instance;
    else
        parent.down = instance;
    end

    instance.setStateFunction = parent.setStateFunction;
    instance.getStateFunction = parent.getStateFunction;
    
    return instance;
end;

function Rocker:doAction(noEventSend, forceValue)
    self.moveFrame = true;
end;

function Rocker:setActive(isActive)    
    InteractiveComponentInterface.setActive(self, isActive)
    self.parent:setActive(isActive)    
    if increase then
        self.parent.down:setActive(isActive)    
    else
        self.parent.up:setActive(isActive)    
    end
end    

function Rocker:update(dt)    
    if self.parent.isActive then
        local isPlaying   = self.vehicle:getIsAnimationPlaying( self.parent.animation )
        local curAnimTime = self.parent.defaultAnimTime
        if isPlaying then
            animation = self.vehicle.animations[self.parent.animation]
            if animation.stopTime ~= nil then
                curAnimTime = animation.stopTime / animation.duration
            elseif animation.currentSpeed < 0 then
                curAnimTime = 0
            else
                curAnimTime = 1
            end
        else
            curAnimTime = self.vehicle:getAnimationTime( self.parent.animation )
        end
        
        local tgtAnimTime = curAnimTime
        local playAnim    = false
        
        if self.moveFrame then
            if self.parent.moveTime == nil or math.abs( self.parent.moveTime ) < 0.001 then
                step = 0.5
            else
                step = math.min( 0.001*dt/self.parent.moveTime, 0.5 )
            end        
            if not ( self.increase ) then
                step = -step
            end
            self.moveFrame = nil 
            
            tgtAnimTime = Utils.clamp( curAnimTime + step, 0, 1)
            playAnim    = true
            if self.setStateFunction ~= nil then
                self.setStateFunction( self.vehicle, tgtAnimTime )
            end
        elseif self.getStateFunction ~= nil then
            tgtAnimTime = self.getStateFunction( self.vehicle )
            if math.abs( curAnimTime - tgtAnimTime ) > 0.01 then
                playAnim  = true
            end
        end
        
        if playAnim then
            if InteractiveComponentInterface.playAnimationToTime( self.vehicle, self.parent.animation, tgtAnimTime ) then
                if self.animation ~= nil then
                    self.vehicle:playAnimation( self.animation, 1, 0, true);
                end
            end
        end

        if     self.increase and curAnimTime >= 1 then
            self.isOpen = false
        elseif not( self.increase ) and curAnimTime <= 0 then 
            self.isOpen = false
        else
            self.isOpen = true
        end
    
        self.isActive = self.isOpen 
    else
        self.isActive = false
    end;
end;

function Rocker:getSaveAttributes()
    local curAnimTime = Utils.clamp(self.vehicle:getAnimationTime(self.parent.animation), 0, 1)
    if self.parent.defaultAnimTime == nil or math.abs( curAnimTime - self.parent.defaultAnimTime ) > 1E-4 then
        return "animationTime=\""..tostring(curAnimTime).."\""
    end
    return ""
end

function Rocker:setSaveAttributes(xmlFile, xmlName)
    local tgtAnimTime = getXMLFloat(xmlFile, xmlName .. "#animationTime")
    if tgtAnimTime ~= nil then
        self.vehicle:setAnimationTime( self.parent.animation, tgtAnimTime, true )
    end
end