#include "structs.h"

#define smallDevFont (0x82997604)
#define consoleFont (0x8299761C)
#define bigFont (0x82997634)
#define smallFont (0x8299764C)
#define boldFont (0x82997664)
#define normalFont (0x8299767C)
#define extraBigFont (0x82997694)
#define objectiveFont (0x829976AC)
#define hudBigFont (0x829976C4)
#define hudSmallFont (0x829976DC)
#define bigDevFont (0x829976F4)

float colorBlue[4] = { 0.0f, 0.0f, 1.0f, 1.0f };
float colorWhite[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
float ShaderBlack[4] = { 0.0f, 0.0f, 0.0f, 1.0f };

typedef void (__cdecl *R_AddCmdDrawText_t)(const char *text, int maxChars, void *font, float x, float y, float xScale, float yScale, float rotation, const float *color, int style);
R_AddCmdDrawText_t R_AddCmdDrawText = (R_AddCmdDrawText_t)0x82350258;

typedef int (__cdecl * G_LocalizedStringIndex_t)(const char * string);
G_LocalizedStringIndex_t Localized = (G_LocalizedStringIndex_t)0x8220C838;

typedef game_hudelem_s * (__cdecl * HudElem_Alloc_t)(int clietNum, int teamNum);
HudElem_Alloc_t HudElem_Alloc = (HudElem_Alloc_t)0x821DF9C0;
 
typedef int (__cdecl * G_MaterialIndex_t)(const char * name);
G_MaterialIndex_t G_MaterialIndex = (G_MaterialIndex_t)0x8220C9F8;

typedef void (__cdecl * HECmd_MoveOverTime_t)(scr_entref_t entref);
HECmd_MoveOverTime_t HECmd_MoveOverTime = (HECmd_MoveOverTime_t)0x821E17B8;

typedef void (__cdecl * HECmd_ChangeFontScaleOverTime_t)(scr_entref_t entref);
HECmd_ChangeFontScaleOverTime_t HECmd_ChangeFontScaleOverTime = (HECmd_ChangeFontScaleOverTime_t)0x821E15E0;

typedef void (__cdecl * BG_LERPHUDCOLORS)( game_hudelem_s * elem, int time, hudelem_color_t * toColor );
BG_LERPHUDCOLORS BG_LerpHudColors = (BG_LERPHUDCOLORS)0x820D0460;

typedef void (__cdecl * HECmd_Destroy_t)(scr_entref_t entref);
HECmd_Destroy_t HECmd_Destroy = (HECmd_Destroy_t)0x821E1900;

typedef void (__cdecl * HECmd_ScaleOverTime_t)(scr_entref_t entref);
HECmd_ScaleOverTime_t HECmd_ScaleOverTime = (HECmd_ScaleOverTime_t)0x821E16C0;

typedef void (__cdecl * HECmd_Reset_t)(scr_entref_t entref);
HECmd_Reset_t HECmd_Reset = (HECmd_Reset_t)0x821E18A0;

typedef void (__cdecl * HECmd_SetPulseFX_t)(scr_entref_t entref);
HECmd_SetPulseFX_t HECmd_SetPulseFX = (HECmd_SetPulseFX_t)0x821E1A90;


game_hudelem_s * effect_Shader_newsbar;
game_hudelem_s * effect_Text_newsbar;
game_hudelem_s * effect_Text_pulse;



int getLevelTime()
{
  return *(int *)0x8310A12C;
}


int getElemIndex(game_hudelem_s * elem)
{
    for (int elemId = 0 ;; elemId++)
    {
      if ((int)elem == (0x82ED6560 + (elemId * 0xB4)))
      {
       return elemId;
      }
    }
    
    return -1;
}

scr_entref_t elemEntref(game_hudelem_s * elem)
{
    scr_entref_t entref; 
    entref.entnum = getElemIndex(elem);
    entref.classnum = 1;
    return entref;
}

game_hudelem_s * spawnElem(int clientNum)
{
	game_hudelem_s * elem = HudElem_Alloc(0, 0);
	elem->clientNum = clientNum;
	elem->archived = true;
	return elem;
}

static void Reset2(game_hudelem_s * elem)
{
    HECmd_Reset(elemEntref(elem));
}

static void Reset_Shader(game_hudelem_s * elem)
{
	elem->elem.width = 0;
	elem->elem.height = 0;
	elem->elem.x = -50000;
}

void scaleOverTime(game_hudelem_s * elem, float fromSize, float toSize, int scaleTime)
{
elem->elem.fontScaleStartTime = getLevelTime();
elem->elem.fontScaleTime = scaleTime; 
elem->elem.fromFontScale = fromSize;
elem->elem.fontScale = toSize;
}

void Destroy(game_hudelem_s * elem)
{
 HECmd_Destroy(elemEntref(elem));
}


static void w_h_x(game_hudelem_s * elem, int w, int h, float x)
{
	elem->elem.width = w;
	elem->elem.height = h;
	elem->elem.x = x;
}

static void SetRGB(game_hudelem_s * elem, byte R = 0, byte G = 230, byte B = 255) // byte R = 255, byte G = 255, byte B = 255
{
	elem->elem.color.r = R;
	elem->elem.color.g = G;
	elem->elem.color.b = B;
}

void setText(game_hudelem_s * elem, const char * text, int font, float fontScale, float x, float y, int alignOrg, int alignScreen, float sort = 1, byte r = 0, byte g = 230, byte b = 255, byte a = 255) // byte r = 255, byte g = 255, byte b = 255, byte a = 255
{
	 
	elem->elem.type = 0x01;
	elem->elem.alignOrg = alignOrg;
	elem->elem.alignScreen = alignScreen;
	elem->elem.font = font;
	elem->elem.fontScale = fontScale;
	elem->elem.x = x;
	elem->elem.y = y;
	elem->elem.color.r = r;
	elem->elem.color.g = g;
	elem->elem.color.b = b;
	elem->elem.color.a = a;
	elem->elem.sort = sort;
	elem->elem.text = Localized(text);
}

// Status: (At the top)

void setShader(game_hudelem_s * elem, const char * materialName, int width, int height, float sort, float x, float y, int alignOrg, int alignScreen, byte a = 255, byte r = 0, byte g = 230, byte b = 255) // byte a = 255, byte r = 255, byte g = 255, byte b = 255
{
	elem->elem.type = 0x04;
	elem->elem.alignOrg = alignOrg;
	elem->elem.alignScreen = alignScreen;
	elem->elem.x = x;
	elem->elem.y = y;
	elem->elem.color.r = r;
	elem->elem.color.g = g;
	elem->elem.color.b = b;
	elem->elem.color.a = a;
	elem->elem.width = width;
	elem->elem.height = height;
	elem->elem.sort = sort;
	elem->elem.materialIndex = G_MaterialIndex(materialName);
}

void moveOverTime(game_hudelem_s * elem, float endX, float endY, int moveTime, bool scrollText = false)
{
	float x = elem->elem.x;
	float y = elem->elem.y;
	int alignOrg = elem->elem.alignOrg;
	int alignScreen = elem->elem.alignScreen;

	elem->elem.moveStartTime = getLevelTime();
	elem->elem.moveTime = moveTime;

	elem->elem.alignOrg = 0x05;
	elem->elem.alignScreen = BOTTOM_CENTER;
	elem->elem.fromX = 1500;
	elem->elem.fromY = 26;
	elem->elem.fromAlignOrg = 0x05;
	elem->elem.fromAlignScreen = BOTTOM_CENTER;

	elem->elem.y = endY;
	elem->elem.x = endX;
}

void moveOverTime_elem( game_hudelem_s * elem, float time, int startTime = getLevelTime())
{
    if (time <= 0)
    {
        return;
    }
    else if (time > 60)
    {
        return;
    }
 
    int * levelTime = (int*)0x8310A12C;
    elem->elem.fromAlignOrg = elem->elem.alignOrg;
    elem->elem.fromAlignScreen = elem->elem.alignScreen;
    elem->elem.fromX = elem->elem.x;
    elem->elem.fromY = elem->elem.y;
    elem->elem.moveStartTime = startTime;
    elem->elem.moveTime = (int)floor( time * 1000 + 0.5 );
}

void elemMove( game_hudelem_s * elem, char * axis, float calc, float time, int startTime = 0)
{
    moveOverTime_elem(elem, time, getLevelTime()+startTime);
    if ( !strcmp(axis, "x"))
	{
        elem->elem.x = calc;
	}
    else
	{   

	}
}

void fadeOverTime( game_hudelem_s * elem, float time )
{
    if ( time <= 0 )
    {
//        DbgPrint( "fade time %g <= 0\n", time );
        return;
    }
    else if ( time > 60 )
    {
 //       DbgPrint( "fade time %g > 60\n", time );
        return;
    }
 
    int * levelTime = (int*)0x8310A12C;
    BG_LerpHudColors( elem, *levelTime, &(elem->elem.fromColor) );
 
    elem->elem.fadeStartTime = *levelTime;
    elem->elem.fadeTime = (int)floor( time * 1000 + 0.5 );
}
