Animator = {}

function Animator:new(looped)
    local x = copy_table(self)
    x:init(looped)
    return x
end


function Animator:init(looped)
    self.time = 0
    self.total_time = 0
    self.val = {}
    self.keys = {}
    self.looped = looped or false
end

function Animator:key(name, data, interpolation)
    for k,v in pairs(data) do
        self:add_key(name, v[1], v[2])
    end
end


function Animator:add_key(name, time, value)
    if not self.keys[name] then
        self.keys[name] = {}
    end
    table.insert(self.keys[name], { time = time, value = value })
    table.sort(self.keys[name], function(a,b) return a.time < b.time end)
    self.val[name] = self.keys[name][1].value
    if time > self.total_time then
        self.total_time = time
    end
end


function Animator:is_finished()
    return self.time >= self.total_time
end


function Animator:restart()
    self.time = 0
end


function Animator:update(dt)
    self.time = self.time + dt
    if self.looped and self.time >= self.total_time then
        self.time = self.time - self.total_time
    end
    local i
    local t = self.time
    local t0
    local v0

    for k,v in pairs(self.keys) do
        i = 1
        while v[i] and t >= v[i].time do
            i = i + 1
        end
        if v[i] then
            t0 = v[i-1].time
            v0 = v[i-1].value
            self.val[k] = v0 + (v[i].value - v0) * (t - t0) / (v[i].time - t0)
        else
            self.val[k] = v[i-1].value
        end
    end
end


----------------------------------------------------------------------

function test_animator()
    local ani = Animator:new()
    ani:add_key("x", 0, 100)
    ani:add_key("x", 0.6, 220)
    ani:add_key("y", 0, 200)
    ani:add_key("y", 0.2, 210)
    ani:add_key("y", 0.6, 500)

    log("--- Animator test start ----------------------")
    while not ani:is_finished() do
        ani:update(0.1)
        log("x = "..ani.val.x..", y = "..ani.val.y)
    end
    log("--- Animator test end ------------------------")
end
