/* errors.c */

#include "computorv1.h"

static void print_context_input()
{
    ft_dprintf(STDERR_FILENO, "\ninput : %s\n", input_g_err);
}

static void print_context_tokens()
{
    int i;

    ft_putchar_fd('\n', STDERR_FILENO);
    i = 0;
    while (tokens_g_err[i].type != TOKEN_END)
    {
        ft_dprintf(STDERR_FILENO, "token[%2i] - type : %22s", i, token_type_to_str(tokens_g_err[i].type));

        ft_putstr(" - value : ");
        if (tokens_g_err[i].type == TOKEN_NUMBER_INT)
        {
            ft_dprintf(STDERR_FILENO, "%i\n", tokens_g_err[i].value_int);
        }
        else if (tokens_g_err[i].type == TOKEN_NUMBER_INT_SUPER)
        {
            ft_dprintf(STDERR_FILENO, "%i\n", tokens_g_err[i].value_int);
        }
        else if (tokens_g_err[i].type == TOKEN_NUMBER_DOUBLE)
        {
            dprintf(STDERR_FILENO, "%g\n", tokens_g_err[i].value_double);
        }
        else
        {
            ft_dprintf(STDERR_FILENO, "%c\n", tokens_g_err[i].value_char);
        }
        i++;
    }
    ft_putchar_fd('\n', STDERR_FILENO);
}

static void print_context_terms()
{
    int i;

    i = 0;
    while (terms_g_err[i].position != TERM_END)
    {
        ft_dprintf(STDERR_FILENO, "term[%2i] - ", i);
        ft_dprintf(STDERR_FILENO, "%8s : %10s", "position", term_position_to_str(terms_g_err[i].position));
        ft_dprintf(STDERR_FILENO, " | %4s : %10s", "sign", term_sign_to_str(terms_g_err[i].sign));
        dprintf(STDERR_FILENO, " | %10s : %13g", "coefficient", terms_g_err[i].coefficient);
        ft_dprintf(STDERR_FILENO, " | %8s : %d\n", "exponent", terms_g_err[i].exponent);
        i++;
    }
    ft_putchar_fd('\n', STDERR_FILENO);
}

static void print_context_polynom()
{
    int i;

    i = 0;
    while (i <= polynom_len_g_err)
    {
        dprintf(STDERR_FILENO, "polynom[%i]: %c -> %10g\n", i, i + 'a', polynom_g_err[i]);
        i++;
    }
    ft_putchar_fd('\n', STDERR_FILENO);
}

static void print_context_solution()
{
    dprintf(STDERR_FILENO, "delta_sign             : %25s\n", delta_sign_to_str(solution_g_err->delta_sign));
    dprintf(STDERR_FILENO, "delta_absolute         : %25g (|b² - 4ac|)\n", solution_g_err->delta_absolute);
    dprintf(STDERR_FILENO, "first_term_gcd         : %25i\n", solution_g_err->first_term_gcd);
    dprintf(STDERR_FILENO, "first_term_numerator   : %25i (-b / gcd)\n", solution_g_err->first_term_numerator);
    dprintf(STDERR_FILENO, "first_term_denominator : %25i (2a / gcd)\n", solution_g_err->first_term_denominator);
    dprintf(STDERR_FILENO, "first_term             : %25g (-b / 2a)\n", solution_g_err->first_term);
    // dprintf(STDERR_FILENO, "second_term_gcd        : %25g\n", solution_g_err->second_term_gcd);
    // dprintf(STDERR_FILENO, "second_term_numerator  : %25g\n", solution_g_err->second_term_numerator);
    // dprintf(STDERR_FILENO, "second_term_denominator: %25g\n", solution_g_err->second_term_denominator);
    // dprintf(STDERR_FILENO, "second_term            : %25g\n", solution_g_err->second_term);
    // dprintf(STDERR_FILENO, "solution1              : %25g\n", solution_g_err->solution1);
    // dprintf(STDERR_FILENO, "solution2              : %25g\n", solution_g_err->solution2);

    ft_putchar_fd('\n', STDERR_FILENO);
}

void print_state()
{
    if (!flag_debug_mode)
        return;
    ft_dprintf(STDERR_FILENO, "\nSTATE :\n");
    if (input_g_err)
        print_context_input();
    if (tokens_g_err)
        print_context_tokens();
    if (terms_g_err)
        print_context_terms();
    if (polynom_g_err)
        print_context_polynom();
    if (solution_g_err)
        print_context_solution();
}

void stop_errors(const char *description, ...)
{
    // print context
    if (flag_debug_mode)
    {
        print_state();
    }

    // print red ERROR
    if (flag_debug_mode)
    {
        ft_putstr_fd("\e[1;31mERROR:\e[0m ", STDERR_FILENO);
    }

    // print the formatted description
    va_list args;
    va_start(args, description);
    ft_vdprintf(STDERR_FILENO, description, args);
    va_end(args);

    // print the base message
    if (flag_debug_mode)
    {
        ft_dprintf(STDERR_FILENO, " (errno[%d] : %s)\n", errno, strerror(errno));
    }

    // stop program
    exit(EXIT_FAILURE);
}