/*Copyright (C) 2010-2023 Duncan Deveaux

This file is part of Hikou no mizu.

Hikou no mizu is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Hikou no mizu is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Hikou no mizu.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "Audio/Audio.hpp"
#include "Graphics/Window.hpp"
#include "Configuration/Configuration.hpp"
#include "Engines/GameEngine.hpp"
#include "Engines/Resources/JoystickManager.hpp"
#include "Engines/Sound/PlaylistPlayer.hpp"
#include "Tools/I18n.hpp"
#include "Tools/Log.hpp"
#include "Tools/Format.hpp"
#include "Tools/BuildValues.hpp" ///< Generated at build time
#include <SDL2/SDL_image.h>
#include <cstdlib>

bool initializeAL()
{
    if (!Audio::init())
    {
        Log::err("OpenAL initialization failed");
        return false;
    }

    Log::info(Format::format("OpenAL {} ({})\n  Renderer: {}",
                             alGetString(AL_VERSION),
                             alGetString(AL_VENDOR),
                             alGetString(AL_RENDERER)));
    return true;
}

bool initializeSDL()
{
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) < 0)
    {
        Log::err(Format::format("SDL initialization failed: {}",
                                SDL_GetError()));
        return false;
    }

    SDL_version compiled, linked;
    SDL_VERSION(&compiled);
    SDL_GetVersion(&linked);
    Log::info(Format::format("SDL {}.{}.{} (compiled: {}.{}.{})",
                            +linked.major, +linked.minor, +linked.patch,
                            +compiled.major, +compiled.minor, +compiled.patch));

    if (IMG_Init(IMG_INIT_PNG) != IMG_INIT_PNG)
    {
        Log::err(Format::format("SDL_image initialization failed: {}",
                                IMG_GetError()));
        SDL_Quit();
        return false;
    }

    return true;
}

bool initialize()
{
    if (!initializeSDL())
        return false;
    else if (!initializeAL())
    {
        IMG_Quit();
        SDL_Quit();
        return false;
    }

    return true;
}

void deinitialize()
{
    Audio::close();
    IMG_Quit();
    SDL_Quit();
}

int main(int, char**)
{
    //Hikou no mizu
    Log::info("Hikou no mizu " + BuildValues::VERSION.text(),
              Log::Decoration(Color(255, 255, 255), Color(46, 93, 152),
                              Log::Decoration::Emphasis::Bold));

    //Configuration and locale
    Configuration confManager;
    confManager.load();

    I18n::loadEntries(confManager.getLocale());

    //Initialize display and audio
    if (!initialize())
        return EXIT_FAILURE;

    Window window;
    if (!window.create("Hikou no mizu",
                       confManager.getDisplayLayout(),
                       confManager.getVSyncMode()))
    {
        deinitialize();
        return EXIT_FAILURE;
    }

    window.setIcon( BuildValues::data("gfx/icon.png") );
    window.setFrameRate(static_cast<float>(confManager.getFrameRate()));
    window.initView(static_cast<float>(confManager.getDisplayLayout().width),
                    static_cast<float>(confManager.getDisplayLayout().height));

    //Joystick
    JoystickManager joyManager;
    joyManager.loadJoysticks();

    //Game engine loop
    GameEngine gameEngine(window, confManager, joyManager);
    gameEngine.initMainMenu();

    while (!gameEngine.wasExited())
        gameEngine.launchNextScreen();

    //Save & free resources
    confManager.save();
    joyManager.free();

    PlaylistPlayer::stop();
    window.destroy();
    deinitialize();

    return EXIT_SUCCESS;
}
