--
-- Specialization for Animations
-- This script can be used to play animations that use the AnimatedVehicle specializations
--
--
-- @author:        Marcus Hedblom a.k.a Xentro (www.ls-uk.info)
-- @email:        Marcus@Xentro.se
-- @version:    v1.1
-- @date:        22/10/11
-- @history:    v1.0 - inital implementation
--                 v1.1 - added save/load function
--
--


-- <standardAnimations>
--       <part name="animationName" inputName="BUTTONNAME" helpTextNamePos="110n_help_text_open" helpTextNameNeg="110n_help_text_close" />
-- </standardAnimations>

Animation = {};

function Animation.prerequisitesPresent(specializations)
    if not SpecializationUtil.hasSpecialization(AnimatedVehicle, specializations) then print("Warning: Specialization Animation needs the specialization AnimatedVehicle"); end;
    return SpecializationUtil.hasSpecialization(AnimatedVehicle, specializations);
end;

function Animation:load(savegame)
    print("Animation: load("..self.xmlFile..")");
    
    self.setPlayAnim = SpecializationUtil.callSpecializationsFunction("setPlayAnim");

    self.PAs = {};
    local i=0;
    while true do
        local baseName = string.format("vehicle.standardAnimations.part(%d)", i);
        if not hasXMLProperty(self.xmlFile, baseName) then
            break;
        end;
        local PA = {};
        local name = getXMLString(self.xmlFile, baseName .. "#name");
        local inputName = getXMLString(self.xmlFile, baseName .. "#inputName");
        if name == nil or InputBinding[inputName] == nil or self.animations[name] == nil then
            if self.animations[name] == nil then print("Error: Can't find the animation ("..tostring(name)..") for standardAnimations part number "..i); end;
            if InputBinding[inputName] == nil then print("Error: Can't find the InputBinding ("..tostring(inputName)..") for standardAnimations part number"..i); end;
            break;
        end;
        PA.aName = name;
        PA.inputName = inputName;
        
        PA.helpTextNameP = getXMLString(self.xmlFile, baseName .. "#helpTextNamePos");
        PA.helpTextNameN = getXMLString(self.xmlFile, baseName .. "#helpTextNameNeg");
        
        if g_i18n:hasText(PA.helpTextNameP) or g_i18n:hasText(PA.helpTextNameN) then PA.helpText = true; else PA.helpText = false; end;
        if g_i18n:hasText(PA.helpTextNameP) and g_i18n:hasText(PA.helpTextNameN) then PA.multiHelpText = true; else PA.multiHelpText = false; end;
            
        PA.aFinished = false;
        
        table.insert(self.PAs, PA);
        i = i+1;
    end;
end;

function Animation:delete()
end;

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

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

function Animation:readStream(streamId, connection)
    for k,v in ipairs(self.PAs) do
        local state = streamReadBool(streamId);
        self:setPlayAnim(k,state,true);
    end;
end;
    
function Animation:writeStream(streamId, connection)
    for k,v in ipairs(self.PAs) do
        streamWriteBool(streamId, v.aFinished);
    end;
end;

function Animation:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)
    if not resetVehicles then        
        local numPlayStandAnim = getXMLInt(self.xmlFile, key.."#numPlayStandAnim");
        if numPlayStandAnim ~= nil then
            for i=1, numPlayStandAnim do
                local bKey = key..string.format(".Animation(%d)", i-1);
                local state = Utils.getNoNil(getXMLBool(self.xmlFile, bKey.."#aFinished"),false);
                local animTime = Utils.getNoNil(getXMLFloat(self.xmlFile, bKey.."#time"), -1);
                if state ~= nil then
                    self:setPlayAnim(i,state);
                end;
            end;
        end;
    end; 
    return BaseMission.VEHICLE_LOAD_OK;
end;

function Animation:getSaveAttributesAndNodes(nodeIdent)
    local attributes = 'numPlayStandAnim="'..table.getn(self.PAs)..'" ';
    local nodes = "";
    local numAnim = 0;
    for i=1, table.getn(self.PAs) do
        local b = self.PAs[i];
        if numAnim > 0 then
            nodes = nodes.."\n";
        end;
        nodes = nodes..nodeIdent..'<Animation aFinished="'..tostring(b.aFinished)..'" time="'..self:getAnimationTime(b.aName)..'"';
        nodes = nodes..' />';
        numAnim = numAnim+1;
    end;
    
    return attributes, nodes;
end;

function Animation:update(dt)
    if self:getIsActiveForInput() then
        for k,v in ipairs(self.PAs) do
            if InputBinding.hasEvent(InputBinding[v.inputName]) then
                self:setPlayAnim(k, not v.aFinished); 
            end;
        end;
    end;
end;

function Animation:draw()
    if g_currentMission.showHelpText then
        for k,v in ipairs(self.PAs) do
            if v.helpText then
                if v.multiHelpText then
                    if v.aFinished then
                        g_currentMission:addHelpButtonText(g_i18n:getText(v.helpTextNameN), InputBinding[v.inputName]);
                    else
                        g_currentMission:addHelpButtonText(g_i18n:getText(v.helpTextNameP), InputBinding[v.inputName]);
                    end;
                else
                    if v.helpTextNameP ~= nil then
                        g_currentMission:addHelpButtonText(g_i18n:getText(v.helpTextNameP), InputBinding[v.inputName]);
                    elseif v.helpTextNameN ~= nil and v.helpTextNameP == nil then
                        g_currentMission:addHelpButtonText(g_i18n:getText(v.helpTextNameN), InputBinding[v.inputName]);
                    end;
                end;
            end;
        end;
    end;
end;

function Animation:setPlayAnim(id,state,noEventSend)
    local v = self.PAs[id];
    if v ~= nil and state ~= nil then
        if state then
            if v.aName ~= nil and self.playAnimation ~= nil then
                self:playAnimation(v.aName, 1, nil, true);
                v.aFinished = state;
            end;
        else
            if v.aName ~= nil and self.playAnimation ~= nil then
                self:playAnimation(v.aName, -1, nil, true);
                v.aFinished = state;
            end;
        end;
        setPlayAnimeEvent.sendEvent(self,id,state,noEventSend);
    end;
end;

-- Event --
setPlayAnimeEvent = {};
setPlayAnimeEvent_mt = Class(setPlayAnimeEvent, Event);
InitEventClass(setPlayAnimeEvent, "setPlayAnimeEvent");

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

function setPlayAnimeEvent:new(object, id, state)
    local self = setPlayAnimeEvent:emptyNew()
    self.object = object;
    self.id = id;
    self.state = state;
    return self;
end;

function setPlayAnimeEvent:readStream(streamId, connection)
    self.object = networkGetObject(streamReadInt32(streamId));
    self.id  = streamReadInt8(streamId);
    self.state = streamReadBool(streamId);
    self:run(connection);
end;

function setPlayAnimeEvent:writeStream(streamId, connection)
    streamWriteInt32(streamId, networkGetObjectId(self.object));
    streamWriteInt8(streamId, self.id);
    streamWriteBool(streamId, self.state);
end;

function setPlayAnimeEvent:run(connection)
    self.object:setPlayAnim(self.id,self.state, true);
    if not connection:getIsServer() then
        g_server:broadcastEvent(setPlayAnimeEvent:new(self.object, self.id, self.state), nil, connection, self.object);
    end;    
end;

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