#ifndef __GOLDMODULEMAIN_H
#define __GOLDMODULEMAIN_H

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <iostream>
#include <sstream>
#include <list>
#include <csignal>
#include <chrono>
#include <thread>
#include <ctime>
#include <future>
#include <regex>

#ifdef __LIN_OS__
#include <immintrin.h>
#include <smmintrin.h>
#include <pmmintrin.h>
#endif

#include "../Include/OSDef.h"
#include "../Include/XMLParser.h"
#include "../Include/TextData.h"
#include "../Include/MDFUtil.h"
#include "../Include/GlobalConfig.h"


unsigned long int ulRetEAX = 0;
unsigned long int ulRetEDX = 0;

XMLParser xd;

// Declare config object
TextData td;

#define CLOCKS_PER_MS (CLOCKS_PER_SEC / 1000)

//std::time_t tCurrentTime = std::time(nullptr);
std::time_t tStartTime;
std::time_t tEndTime;
std::time_t tTotalTime;

clock_t start;
clock_t timeElapsed;
unsigned msElapsed;
unsigned msTarget;

enum ReturnValueDef
{
	Success = 0,
	Fail,
	Indeterminate,
	NoCompare,
	InvalidArgs,
	ConfigMismatch
};

enum TextColor
{
	Red = 0,
	Green,
	Yellow
};

enum VarType
{
	vtINT = 0,
	vtSTRING
};

std::string sgGoldModuleResultsFile = "MMXSSE_Results.txt";
int igPassFailStatus = 0;  // Default with success
int igPrintConfig = 0;
int igPauseApp = 0;
int igDefaultLoadTimeInMins = 0;
int iColorText = 0;
int iDebugFlag = 0;
int iPrintVersionFlag = 1;
int iPrintSuccessFlag = 1;

int iSec;
int iMin;
int iHour;
int iOptionValid;
int iRun;
int iArgIndex;

std::string sgGoldModuleVersion;
std::string strPFOut;

// Prototypes
void Init(void);
bool is_integer(const std::string & s);
bool isOptionValid(int iArgLocal, int argcLocal, char *argvLocal[], VarType vt);
void PrintColorMsg(std::string sMsg, TextColor iColor);
void PauseWQuit(void);
void PrintVersion(void);
void SignalFun(int iSigNum);
void CleanUp(void);
void WriteResultsFile(int iPassFailStatus);
void HelpUseage(void);
void ReadLocalConfig(void);
void ReadLocalTextConfig(void);

//Define flags in ECX/RCX registry for MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1 & SSe4.2
#define MMXHWFlag (1UL<<23) 
#define SSEHWFlag (1UL<<25) 
#define SSE2HWFlag (1UL<<26) 
#define SSE3HWFlag (1UL<<0) 
#define SSSE3HWFlag (1UL<<9) 
#define SSE41HWFlag (1UL<<19)
#define SSE42HWFlag (1UL<<20)

typedef union
{
	__m128i					m128i_a;
	__int32					m128i_a_[16];
	__int8					m128i_i8[16];
	__int8					m128i_i8_[16];
	__int16  				m128i_i16[8];
	__int16					m128i_i16_[8];
	__int32					m128i_i32[4];
	__int32					m128i_i32_[4];
	__int64					m128i_i64[2];
	__int64					m128i_i64_[2];
	unsigned __int8			m128i_u8[16];
	unsigned __int8			m128i_u8_[16];
	unsigned __int16         m128i_u16[8];
	unsigned __int16         m128i_u16_[8];
	unsigned __int32         m128i_u32[8];
	unsigned __int32         m128i_u32_[8];
	unsigned __int64		    m128i_u64[2];
	unsigned __int64		    m128i_u64_[2];
	float                    m256_f32[8];
}
m128i_;


typedef union
{
	float                    m128d_f64[2];
	float                    m128d_f64_[2];
	__m128d					m128d_c;
}
m128d_;

typedef union
{
	float                    m128_f32[4];
	float                    m128_f32_[4];
	__m128					m128_d;
}
m128_;

typedef struct
{
	double real;
	double img;
}
complex_num;

extern bool testmmx();
extern bool testsse();
extern bool testsse2();
extern bool testsse3();
extern bool testssse3();
extern bool testsse41();
extern bool testsse42();


#endif  //__GLOBALCONFIG_H