#include <stdio.h>
#include <allegro5/allegro.h>
#include <allegro5/allegro_font.h>
#include <allegro5/allegro_primitives.h>
#include <allegro5/allegro_ttf.h>
#include "GameTypes.h"
#include "Menu.h"
#include "Text.h"

// The ALLEGRO_DISPLAY representing the content of the screen.
ALLEGRO_DISPLAY* display_ = NULL;

// Locate the path to the configuration file.
// The file should be in the current directory or a parent directory.
ALLEGRO_PATH* locateConfigPath(const char* filename);

// Calculate the scale factor for the game based on the screen resolution.
u8 calculateScaleFactor(u16 screenWidth, u16 screenHeight);

int main()
{
    ALLEGRO_PATH* configPath = locateConfigPath("game.cfg");
    ALLEGRO_CONFIG* config = NULL;
    u16 screenWidth = 0;
    u16 screenHeight = 0;

    if (configPath == NULL)
    {
        return -1;
    }

    config = al_load_config_file(al_path_cstr(configPath, '/'));

    if (!al_init())
    {
        fprintf(stderr, "failed to initialise allegro!\n");

        return -2;
    }

    if (!al_init_font_addon())
    {
        fprintf(stderr, "failed to initialise font addon!\n");

        return -3;
    }

    if (!al_init_ttf_addon())
    {
        fprintf(stderr, "failed to initialise ttf addon!\n");

        return -4;
    }

    if (!al_init_primitives_addon())
    {
        fprintf(stderr, "failed to initialise primitives addon!\n");

        return -5;
    }

    screenWidth = atoi(al_get_config_value(config, "", "display_width"));
    screenHeight = atoi(al_get_config_value(config, "", "display_height"));

    display_ = al_create_display(screenWidth, screenHeight);
    al_set_window_title(display_, "TINS 2024");

    // Calculate the scale factor which will determine what multiple of 16 to use for sprites.
    scaleFactor = calculateScaleFactor(screenWidth, screenHeight);

    if (!display_)
    {
        fprintf(stderr, "failed to create display!\n");

        return -6;
    }

    initFonts(al_get_config_value(config, "", "font"));

    // Initialise the sprite sets used by allegro.
    initAllAllegroSpriteSets(0);

    // Runs the game menu including menu loop.
    runMenu(config, configPath);

    // Destroy the sprite sets used by allegro.
    destroyAllAllegroSpriteSets();

    // Cleanup allegro.
    destroyFonts();

    al_destroy_path(configPath);
    al_shutdown_ttf_addon();
    al_shutdown_font_addon();
    al_shutdown_primitives_addon();
    al_destroy_display(display_);
}

ALLEGRO_PATH* locateConfigPath(const char* filename)
{
    // Start from the current directory and assume that the config file is in this directory.
    ALLEGRO_PATH* directory = al_create_path(al_get_current_directory());
    al_set_path_filename(directory, filename);

    // Make sure that the directory is still valid.
    while (al_get_path_num_components(directory) > 0)
    {
        // Check if the config file exists in the directory.
        if (al_filename_exists(al_path_cstr(directory, '/')))
        {
            return directory;
        }
        else
        {
            // Remove the part of the directory before the filename.
            al_remove_path_component(directory, -1);
        }
    }

    // Cleanup the directory created.
    al_destroy_path(directory);

    // Return NULL as the filename does not exist.
    return NULL;
}

u8 calculateScaleFactor(u16 screenWidth, u16 screenHeight)
{
    // The scale factor is the amount that the sprite width can be multiplied by (in multiples of 16).
    // 320x200 = 16->16
    // 640x400 = 16->32
    // 960x600 = 16->48
    // 1280x800 = 16->64
    // 1600x1000 = 16->80
    // 1920x1200 = 16->96
    u8 xScaleFactor = screenWidth / 320;
    u8 yScaleFactor = screenHeight / 200;

    if (xScaleFactor > yScaleFactor)
    {
        return yScaleFactor;
    }
    else
    {
        return xScaleFactor;
    }
}
