#include "application.h"
#include "scenes.h"
#include "utils.h"

typedef struct scene_splash_s
{
    bool   running;
    bool   finish;
    bool   draw; // нужен этот костыль, чтобы небыло мерцаний между переключением сцен :(
    bool   out;
    int    alpha;
    int    speed;
    rgba_t clear_color;
} scene_splash_t;

static scene_t        current_scene = SCENE_NONE;
static scene_t        next_scene    = SCENE_NONE;
static scene_splash_t scene_splash;

static void _Scene_SetSplashSpeed(int speed)
{
    scene_splash.speed = speed;

    if (scene_splash.speed < 1)
        scene_splash.speed = 1;

    if (scene_splash.speed > MAX_SPLASH_SPEED)
        scene_splash.speed = MAX_SPLASH_SPEED;
}

static void _Scene_Splash_Update(float dt)
{
    if (scene_splash.running)
    {
        if (scene_splash.out)
        {
            scene_splash.alpha += scene_splash.speed;

            if (scene_splash.alpha > 255)
            {
                scene_splash.running = false;
                scene_splash.finish  = true;
                scene_splash.alpha   = 255;
            }
        }
        else
        {
            scene_splash.alpha -= scene_splash.speed;

            if (scene_splash.alpha < 0)
            {
                scene_splash.running = false;
                scene_splash.finish  = true;
                scene_splash.draw    = false;
                scene_splash.alpha   = 0;
            }
        }
    }
}

static void _Scene_Splash_Draw(SDL_Renderer *renderer)
{
    if (scene_splash.draw)
    {
        SDL_Rect rect = Utils_GetRect(0, 0, Application_GetWidth(), Application_GetHeight());

        SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
        SDL_SetRenderDrawColor(renderer, 0, 0, 0, scene_splash.alpha);
        SDL_RenderFillRect(renderer, &rect);
        SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
        SDL_SetRenderDrawColor(renderer, scene_splash.clear_color.r, scene_splash.clear_color.g, scene_splash.clear_color.b, scene_splash.clear_color.a);
    }
}

void Scene_Set(scene_t scene)
{
    next_scene = scene;
}

void Scene_Splash_Run(bool out, int speed, rgba_t clear_color)
{
    _Scene_SetSplashSpeed(speed);

    scene_splash.clear_color = clear_color;
    scene_splash.draw        = true;

    // out - затемнение / in - осветление
    if (out)
    {
        scene_splash.running = true;
        scene_splash.finish  = false;
        scene_splash.out     = true;
        scene_splash.alpha   = 0;
    }
    else
    {
        scene_splash.running = true;
        scene_splash.finish  = false;
        scene_splash.out     = false;
        scene_splash.alpha   = 255;
    }
}

bool Scene_Splash_IsFinish(void)
{
    return scene_splash.finish;
}

void Scene_Splash_Stop(void)
{
    scene_splash.running = false;
    scene_splash.finish  = false;
    scene_splash.draw    = false;
    scene_splash.out     = false;
    scene_splash.alpha   = 0;
}

void Scene_Update(float dt)
{
    if (next_scene != SCENE_NONE)
    {
        switch(current_scene)
        {
            case SCENE_INTRO   : Scene_Intro_Free();   break;
            case SCENE_MENU    : Scene_Menu_Free();    break;
            case SCENE_OPTIONS : Scene_Options_Free(); break;
            case SCENE_GAME    : Scene_Game_Free();    break;
            case SCENE_END     : Scene_End_Free();    break;
            default            : break;
        }

        current_scene = next_scene;
        next_scene    = SCENE_NONE;

        switch(current_scene)
        {
            case SCENE_INTRO   : Scene_Intro_Init();   break;
            case SCENE_MENU    : Scene_Menu_Init();    break;
            case SCENE_OPTIONS : Scene_Options_Init(); break;
            case SCENE_GAME    : Scene_Game_Init();    break;
            case SCENE_END     : Scene_End_Init();    break;
            default            : break;
        }
    }

    switch(current_scene)
    {
        case SCENE_INTRO   : Scene_Intro_Update(dt);   break;
        case SCENE_MENU    : Scene_Menu_Update(dt);    break;
        case SCENE_OPTIONS : Scene_Options_Update(dt); break;
        case SCENE_GAME    : Scene_Game_Update(dt);    break;
        case SCENE_END     : Scene_End_Update(dt);    break;
        default            : break;
    }

    _Scene_Splash_Update(dt);
}

void Scene_Draw(SDL_Renderer *renderer)
{
    switch(current_scene)
    {
        case SCENE_INTRO   : Scene_Intro_Draw(renderer);   break;
        case SCENE_MENU    : Scene_Menu_Draw(renderer);    break;
        case SCENE_OPTIONS : Scene_Options_Draw(renderer); break;
        case SCENE_GAME    : Scene_Game_Draw(renderer);    break;
        case SCENE_END     : Scene_End_Draw(renderer);    break;
        default            : break;
    }

    _Scene_Splash_Draw(renderer);
}
