local ffi = require("ffi")
local C = ffi.C
local core = require("pxl8.core")

local anim = {}

local Anim = {}
Anim.__index = Anim

function Anim.new(frame_ids, frame_durations)
    local frame_count = #frame_ids
    local c_frame_ids = ffi.new("u32[?]", frame_count)
    local c_frame_durations = nil

    for i = 1, frame_count do
        c_frame_ids[i-1] = frame_ids[i]
    end

    if frame_durations then
        c_frame_durations = ffi.new("u16[?]", frame_count)
        for i = 1, frame_count do
            c_frame_durations[i-1] = frame_durations[i]
        end
    end

    local a = C.pxl8_anim_create(c_frame_ids, c_frame_durations, frame_count)
    if a == nil then
        return nil
    end
    return setmetatable({ _ptr = a }, Anim)
end

function Anim.from_ase(filepath)
    local a = C.pxl8_anim_create_from_ase(core.gfx, filepath)
    if a == nil then
        return nil
    end
    return setmetatable({ _ptr = a }, Anim)
end

function Anim:add_state(name, state_anim)
    return C.pxl8_anim_add_state(self._ptr, name, state_anim._ptr)
end

function Anim:destroy()
    if self._ptr then
        C.pxl8_anim_destroy(self._ptr)
        self._ptr = nil
    end
end

function Anim:get_current_frame()
    return C.pxl8_anim_get_current_frame(self._ptr)
end

function Anim:get_current_frame_id()
    return C.pxl8_anim_get_current_frame_id(self._ptr)
end

function Anim:get_state()
    local state_name = C.pxl8_anim_get_state(self._ptr)
    if state_name ~= nil then
        return ffi.string(state_name)
    end
    return nil
end

function Anim:has_state_machine()
    return C.pxl8_anim_has_state_machine(self._ptr)
end

function Anim:is_complete()
    return C.pxl8_anim_is_complete(self._ptr)
end

function Anim:is_playing()
    return C.pxl8_anim_is_playing(self._ptr)
end

function Anim:pause()
    C.pxl8_anim_pause(self._ptr)
end

function Anim:play()
    C.pxl8_anim_play(self._ptr)
end

function Anim:render(x, y, w, h, flip_x, flip_y)
    C.pxl8_anim_render_sprite(self._ptr, core.gfx, x, y, w, h, flip_x or false, flip_y or false)
end

function Anim:reset()
    C.pxl8_anim_reset(self._ptr)
end

function Anim:set_frame(frame)
    C.pxl8_anim_set_frame(self._ptr, frame)
end

function Anim:set_loop(loop)
    C.pxl8_anim_set_loop(self._ptr, loop)
end

function Anim:set_reverse(reverse)
    C.pxl8_anim_set_reverse(self._ptr, reverse)
end

function Anim:set_speed(speed)
    C.pxl8_anim_set_speed(self._ptr, speed)
end

function Anim:set_state(name)
    return C.pxl8_anim_set_state(self._ptr, name)
end

function Anim:stop()
    C.pxl8_anim_stop(self._ptr)
end

function Anim:update(dt)
    C.pxl8_anim_update(self._ptr, dt)
end

anim.Anim = Anim

return anim
