------------------------------------------------------------------------------
-- Imports
------------------------------------------------------------------------------

local love        = require 'love'
local assets      = require 'src.utils.asstmngr'
local make_class  = require 'src.utils.classes'
local constants   = require 'src.gstates.menus.const'
local GameState   = require 'src.gstates.gstate'
local MainMenu    = require 'src.gstates.menus.mainmenu'
local OptionsMenu = require 'src.gstates.menus.options'
local Fader       = require 'src.graphics.fader'
local Cursor      = require 'src.ui.cursor'
local Font        = require 'src.ui.font'
local SoundEffect = require 'src.sound.sfx'


------------------------------------------------------------------------------
-- Class definitions
------------------------------------------------------------------------------

local Menu = make_class(GameState)


------------------------------------------------------------------------------
--  Class methods
------------------------------------------------------------------------------

function Menu:_init(name, index)
    GameState._init(self, name, index)
    self.fade         = Fader()
    self.current_menu = constants.MAIN_MENU
    self.next_menu    = constants.MAIN_MENU
    self.all_loaded   = false

    -- Create sprites and buttons.
    self.btn_font   = Font('fonts/Concrete.ttf')
    self.title_font = Font('fonts/BBrick.ttf', 35)

    -- Create a mouse cursor object at the current mouse position.
    local mx, my = love.mouse.getPosition()
    self.cursor  = Cursor(mx, my)

    -- Create sound effects.
    self.bgm = SoundEffect('bgm/eskisky.wav')

    -- Create the sub-menus.
    self.menus = { }
    self.menus[constants.MAIN_MENU]    = MainMenu(self, self.title_font, self.btn_font)
    self.menus[constants.OPTIONS_MENU] = OptionsMenu(self, self.title_font, self.btn_font)

    -- Register all assets.
    assets:register(self.name, self.btn_font)
    assets:register(self.name, self.title_font)
    assets:register(self.name, self.cursor)
    assets:register(self.name, self.bgm)
end


function Menu:update(dt)
    if not self.bgm:isPlaying() then self.bgm:play() end

    if self.all_loaded then
        self.menus[self.current_menu]:update(dt)

        -- If the game state changed then trigger a fade out.
        if self.next_menu ~= self.current_menu and self.fade.done then
            self.fade:fade_out()
        end

        self.fade:update(dt)

        -- Update the game state.
        if self.menus[self.next_menu] == nil then
            error(string.format('%s: switched to unknown menu', self.next_menu))
        else
            -- If the new state exists then unload it's data and set the new state.
            if self.next_menu ~= self.current_menu and self.fade.done then
                self.current_menu = self.next_menu
                self.fade:fade_in()
            end
        end
    else
        local done = true

        assets:update(self.name)

        for _, v in pairs(self.menus) do
            assets:update(v.name)
            done = done and assets:done(v.name)
        end

        self.all_loaded = assets:done(self.name) and done
    end

    return self.next_state
end


function Menu:draw()
    if self.all_loaded then
        self.menus[self.current_menu]:draw()
        self.cursor:draw()
        self.fade:draw()
    else
        assets:draw()
    end
end


function Menu:mousemoved(x, y, dx, dy)
    self.menus[self.current_menu]:mousemoved(x, y, dx, dy)
    self.cursor:mousemoved(x, y, dx, dy)
end


function Menu:mousepressed(x, y, btn)
    if self.fade.done then
        self.menus[self.current_menu]:mousepressed(x, y, btn)
    end
end


function Menu:mousereleased(x, y, btn)
    if self.fade.done then
        self.menus[self.current_menu]:mousereleased(x, y, btn)
    end
end


------------------------------------------------------------------------------
-- Module return
------------------------------------------------------------------------------

return Menu
