#ifndef BACK_BASE_H
#define BACK_BASE_H

int ln_baseN(int n, int b);
int pw(int x, int n);
double pwf(double x, int n);
int abs(int n);
int min(int a, int b);
int max(int a, int b);
double mind(double a, double b);
double maxd(double a, double b);
float minf(float a, float b);
float maxf(float a, float b);
double absf(double n);
bool xor(bool a, bool b);
int reverse(int n);
int convex_seg(int x1, int x2, double theta);
double convex_tri(double a, double tha, double b, double thb, double c, double thc);
pt_2d convex_pt2d(pt_2d A, pt_2d B, double theta);
pt_2d convex_pt2d_tri(pt_2d A, double tha, pt_2d B, double thb, pt_2d C, double thc);
bool is_an_integer(char c);
double to_double(int n);
int to_int(double n);
int line_count(char* filename);
int str_to_int(char* s);
bool str_equal(char* s1, char* s2);
bool pt_equal_3D(pt_2d p1, pt_2d p2);
bool pt_equal_2D(pt_2d p1, pt_2d p2);
bool pt_equal_3D_eps(pt_2d p1, pt_2d p2, double epsilon);
bool pt_equal_2D_eps(pt_2d p1, pt_2d p2, double epsilon, bool debug0);

pt_2d vect_diff(pt_2d p1, pt_2d p2);
double dot2D(pt_2d p1, pt_2d p2);
double dot3D(pt_2d p1, pt_2d p2);

cube_0* create_cube_0(double x, double y, double z, double w, double h, double d, double hz_a, double vt_a, int r, int g, int b);
void fill_cube_0(cube_0* cb, double x, double y, double z, double w, double h, double d, double hz_a, double vt_a, int r, int g, int b);
cube create_cube(double x, double y, double z, double w, double h, double d, double hz_a, double vt_a, int r, int g, int b);
void free_cube(cube c);
teleporter* create_teleporter(
    double x, double y, double z, double w, double h, double d, double hz_a, double vt_a, int r, int g, int b,
    int chx_dest, int chy_dest, double x_dest, double y_dest, double z_dest
);
void copy_cube(cube_0* src, cube_0* dest);

double convex_pt(double a, double b, double theta);
double distance_pt_pt_3d(double x0, double y0, double z0, double x1, double y1, double z1);
double distance_pt_seg_3d(double x, double y, double z, double sx, double sy, double sz, double ex, double ey, double ez);

double convex_pt(double a, double b, double theta);
double distance_pt_pt_3d(double x0, double y0, double z0, double x1, double y1, double z1);
double distance_pt_pt_2d_sq(double x0, double y0, double x1, double y1);
double distance_pt_pt_3d_sq(double x0, double y0, double z0, double x1, double y1, double z1);
double distance_pt_seg_3d(double x, double y, double z, double sx, double sy, double sz, double ex, double ey, double ez);
double distance_pt_cube_0_3d(double x0, double y0, double z0, cube_0* c);
double distance_pt_cube_0_3d_infinite(double x0, double y0, double z0, cube_0* c);

void remove_entity(entity** arr, int* memlen, int* len, int index);
void add_entity(entity** arr, int* memlen, int* len, entity* ent);

void project_to_camera(double x0, double y0, double z0, double* rx, double* ry, double* rz);
void project_to_cube(double x0, double y0, double z0, double* rx, double* ry, double* rz, cube_0* c);

#endif