/* computorv1.h */

#ifndef COMPUTORV1_H
#define COMPUTORV1_H

#include "libft.h"
#include <stdio.h>  // tmp for printf, for float debug
#include <stdarg.h> // for va_list
#include <stdbool.h>

/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * LEXER.C
 */

typedef enum
{
    TOKEN_VARIABLE,      // x, y, etc.
    TOKEN_NUMBER_INT,    // int
    TOKEN_NUMBER_DOUBLE, // double
    TOKEN_POWER,         // ^ or **
    TOKEN_SIGN_PLUS,     // +
    TOKEN_SIGN_MINUS,    // -
    TOKEN_FACTOR_MULT,   // *
    TOKEN_FACTOR_DIV,    // / or :
    TOKEN_EQUAL,         // =
    TOKEN_END            // null (end of input)
} e_token_type;

typedef enum
{
    TOKEN_NO_TAG,
    TOKEN_NUMBER,
    TOKEN_SIGN,
    TOKEN_FACTOR,
} e_token_tag;

typedef struct
{
    e_token_type type;
    e_token_tag tag;
    union
    {
        char value_char;
        int value_int;
        double value_double;
    };
} s_token;

int lexerize(const char *input, s_token *tokens);

/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * PARSER.C
 */

typedef enum
{
    TERM_LEFT,  // a in "a = b"
    TERM_RIGHT, // b in "a = b"
    TERM_END,   // last term
} e_term_position;

typedef enum
{
    TERM_PLUS,  // +
    TERM_MINUS, // -
    TERM_NULL,  // null -> for the last term
} e_term_sign;

typedef struct
{
    e_term_position position;
    e_term_sign sign;
    double coefficient;
    int exponent;
} s_term;

int parse(s_token *tokens, s_term *terms, int terms_count_max);

/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * REDUCE.C
 */

typedef struct
{
    double a;
    double b;
    double c;
} s_polynom;

void reduce(s_term *terms, s_polynom *polynom);

/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * UTILS/ERRORS.C
 */

typedef enum
{
    ERROR_BASE = 1, // start at 1 to avoid exit(0) for errors
    ERROR_TOKEN_COUNT,
    ERROR_UNKNOWN_TOKEN,
    ERROR_NUMBER_TOO_BIG,
    ERROR_PARSING,
    ERROR_TERM_COUNT,
    ERROR_TOKEN_POSITION,
    ERROR_VAR_DIFF,
    ERROR_SENTINEL, // last token not used, only for enum count
} e_program_error;

void print_state();
int stop_errors(e_program_error err, const char *format, ...);

/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * UTILS/PRINT_ENUMS.C
 */

const char *token_type_to_str(e_token_type type);
const char *token_tag_to_str(e_token_tag tag);
const char *term_position_to_str(e_term_position pos);
const char *term_sign_to_str(e_term_sign sign);

/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * GLOBALS
 */

extern char *input_g_err;
extern s_token *tokens_g_err;
extern s_term *terms_g_err;
extern s_polynom *polynom_g_err;

#endif