#include "../Include/MDFUtil.h"

std::fstream fsFileLocalOut;
char Path[136] = "CPUOut.txt";
void CopyFile( std::string file1, std::string file2)
{
    const int BUFFER_SIZE = (16 * 1024);
    char buffer[BUFFER_SIZE];
    int iFile1;
    int iFile2;
    int iReadSize;

    iFile1 = open(file1.c_str(), O_RDONLY);
    if(iFile1 < 0)
    {
        std::cerr << "Error: Unable to open " << file1 << "\n";
        exit(8);
    }
    iFile2 = open(file2.c_str(), O_WRONLY | O_TRUNC | O_CREAT, 0666);
    if(iFile2 < 0)
    {
        std::cerr << "Error: Unable to open " << file2 << "\n";
        exit(8);
    }
    for(;;)
    {
        iReadSize = read(iFile1, buffer, sizeof(buffer));
        if(iReadSize == 0)
        {
            break;
        }
        if(iReadSize < 0)
        {
            std::cerr << "Error: Read error! \n";
            exit(8);
        }
        write(iFile2, buffer, (unsigned int) iReadSize);
    }
    close(iFile1);
    close(iFile2);
    
}

std::string DateTimeToString()
{
  std::string sRet;
  // Get current datetime
  time_t now = time(0);

  // UtilConvert tm struct in local time
  tm* TimeOut = localtime(&now);

  //sRet = asctime(TimeOut);

  //std::string UtilConvert (int number, int numpad, std::string sFill)
    
  sRet += UtilConvert(TimeOut->tm_mon+1, 2, '0') + "/";
  sRet += UtilConvert(TimeOut->tm_mday, 2, '0') + "/";
  sRet += UtilConvert(TimeOut->tm_year+1900, 4, '0') + " ";
    
  sRet += UtilConvert(TimeOut->tm_hour, 2, '0') + ":";
  sRet += UtilConvert(TimeOut->tm_min, 2, '0') + ":";
  sRet += UtilConvert(TimeOut->tm_sec, 2, '0');

    return sRet;
}
std::string compareStringParts(std::string& sStr1, std::string& sStr2, std::vector<std::string>& vDelStrList, bool bPrintStrings)
{
    std::string sRet = "SAME";
    std::vector<std::string> vStr1;
    std::vector<std::string> vStr2;

    if(sStr1.length() < 1 || sStr2.length() < 1)
    {
        return "DIFFERENT";
    }
    int iDelCnt;
    for(iDelCnt = 0; iDelCnt < vDelStrList.size(); iDelCnt++)
    {
        removeSubStrs(sStr1, vDelStrList[iDelCnt]);
    }
    
    for(iDelCnt = 0; iDelCnt < vDelStrList.size(); iDelCnt++)
    {
        removeSubStrs(sStr2, vDelStrList[iDelCnt]);
    }

    Tokenize(sStr1, vStr1);
    Tokenize(sStr2, vStr2);

    if (vStr1.size() == vStr2.size() && std::equal (vStr1.begin(), vStr1.end(), vStr2.begin()))
    {
        sRet = "SAME";
    }
    else
    {
        sRet = "DIFFERENT";
    }

    if(bPrintStrings == true)
    {
        std::cout << std::endl << "String 1: " << std::endl;
        std::copy(vStr1.begin(), vStr1.end(), std::ostream_iterator<std::string>(std::cout, ", "));
        std::cout << std::endl << "String 2: " << std::endl;
        std::copy(vStr2.begin(), vStr2.end(), std::ostream_iterator<std::string>(std::cout, ", "));
    }
    
    return sRet;
}
void SplitString(std::string sInput, std::vector<std::string>&  svOut, char cDelimiter)
{
	//std::vector<std::string> svRet;
	std::string sTemp = "";
	for(int iInputIndex = 0; iInputIndex < sInput.length(); iInputIndex++)
    {
		if(sInput[iInputIndex] == cDelimiter)
		{
			svOut.push_back(sTemp);
			sTemp = "";
		}
		else
		{
			sTemp += sInput[iInputIndex];
		}		
	}
	svOut.push_back(sTemp);
	//return svRet;
}
std::string RemoveCharsFromString(std::string sInput, std::string sCharList)
{

	std::string sRet = "";
	std::vector<std::string>  svCharList;
	bool bFound = false;
	size_t stFoundIndex = 0;
	SplitString(sCharList, svCharList, '|');
	for(int iInputIndex = 0; iInputIndex < sInput.length(); iInputIndex++)
    {
		for(int iCharList = 0; iCharList < svCharList.size(); iCharList++)
		{
			if(svCharList[iCharList].length() == 1)
			{
				if(sInput[iInputIndex] == svCharList[iCharList][0])
				{
					bFound = true;
				}
			}
			else if(svCharList[iCharList].length() > 1)
			{
				if(sInput[iInputIndex] == svCharList[iCharList][0])
				{
					stFoundIndex = sInput.find_first_of(svCharList[iCharList], iInputIndex);
					if(stFoundIndex != std::string::npos && stFoundIndex <= iInputIndex)
					{
						iInputIndex = stFoundIndex + svCharList[iCharList].length();
						bFound = true;
					}
				}
			}
		}
		if(bFound == false)
		{
			sRet += sInput[iInputIndex];
		}
		bFound = false;

	}
	return sRet;
}

void Tokenize(const std::string& str, std::vector<std::string>& tokens, const std::string& delimiters)
{
    // Skip delimiters at beginning.
    std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
    // Find first "non-delimiter".
    std::string::size_type pos     = str.find_first_of(delimiters, lastPos);

    while (std::string::npos != pos || std::string::npos != lastPos)
    {
        // Found a token, add it to the vector.
        tokens.push_back(str.substr(lastPos, pos - lastPos));
        // Skip delimiters.  Note the "not_of"
        lastPos = str.find_first_not_of(delimiters, pos);
        // Find next "non-delimiter"
        pos = str.find_first_of(delimiters, lastPos);
    }
}
void split(const std::string& s, char c, std::vector<std::string>& v, bool bTrim)
{
	std::string::size_type i = 0;
	std::string::size_type j = s.find(c);
	std::string s1;

	while (j != std::string::npos)
	{
        s1 = s.substr(i, j);        
        if(s1.find(c) == std::string::npos)
		{
           if(bTrim == true)
           {
    	     v.push_back(trim(s.substr(i, j-i)," "));
           }
           else
           {
               v.push_back(s.substr(i, j-i));
           }
		}
		i = ++j;
		j = s.find(c, j);

		if (j == std::string::npos)
		{
            if(bTrim == true)
            {
			    v.push_back(trim(s.substr(i, s.length())," "));
            }
            else
            {
                v.push_back(s.substr(i, s.length()));
            }
		}
	}
}

std::string ToUpper(std::string sText)
{
    std::string sRet;
    const char* cText = sText.c_str();
    for(int i = 0; i < sText.length(); i++)
    {
        sRet += toupper(cText[i]);
    }
    return sRet;
}

std::string trim_right(const std::string &source , const std::string& t)
{
std::string str = source;
return str.erase( str.find_last_not_of(t) + 1);
}

std::string trim_left( const std::string& source, const std::string& t )
{
std::string str = source;
return str.erase(0 , source.find_first_not_of(t) );
}

std::string trim(const std::string& source, const std::string& t)
{
std::string str = source;
return trim_left( trim_right( str , t) , t );
} 
void fnOpenFile(std::string sPath)
{
    if(sPath.length() < 1)
    {
        sPath = Path;
    }
    fsFileLocalOut.open(sPath.c_str(), std::ios::out);
}
void fnCloseFile(void)
{    
    fsFileLocalOut.close();
}
int fnWriteToFile(std::string sLineToWrite)
{
	if(fsFileLocalOut.is_open())
	{
		fsFileLocalOut << sLineToWrite;
	}
	return 0;
}

//Function Wait
void Wait ( int seconds )
{
  clock_t endwait;
  endwait = clock() + seconds *CLOCKS_PER_SEC;
  while (clock() < endwait) 
  {
  }
}

//Function Wait_Mils
void WaitMils ( long mils )
{
  clock_t endwait;
  endwait = clock() + mils;
  while (clock() < endwait) 
  {
  }
}

// UtilConvert Int Value to String with padding
std::string UtilConvert (int number, int numpad, char cFill)
{
    std::ostringstream buff;
    buff.fill(cFill);
    buff.width((std::streamsize)numpad);
    buff << std::right << number;
    return buff.str();
}

//Function to UtilConvert Int Value to String
std::string UtilConvert (int number)
{
    std::ostringstream buff;
     buff<<number;
     return buff.str();
}

//Function to UtilConvert long Value to String
std::string UtilConvert (long number)
{
    std::ostringstream buff;
     buff<<number;
     return buff.str();
}

//Function to UtilConvert Float Value to String
std::string UtilConvert (float number)
{
    std::ostringstream buff;
     buff<<number;
     return buff.str();
}
//Function to UtilConvert Double Value to String
std::string UtilConvert(double number)
{
	std::ostringstream buff;
	buff << number;
	return buff.str();
}

//Function Convert ascii-to-integer
//int CustomAsciiToInteger(char *cInput)
int CustomAsciiToInteger(std::string sInput)
{
	int iResult = 0;
	int iSize = sInput.size();

	for (int i = 0, j = iSize; i < iSize; i++)
	{
		iResult += (sInput[--j] - '0')*pow(10, i);
	}
	return iResult;
}


void GetProcFamilyModel(int *CPUfamily, int *CPUmodel, int *CPUstepping)
{
#if defined __WIN_64__ || defined __LIN_64__
	unsigned long long regRAX = 0;

	__asm
	{
		xor rax, rax
			mov rax, 01h
			cpuid
			mov regRAX, rax
	}

	*CPUfamily = (0xF & (regRAX >> 8)) + (0xFF & (regRAX >> 20));
	*CPUmodel = (0xF & (regRAX >> 4)) + ((0xF & (regRAX >> 16)) << 4);
	*CPUstepping = (0xF & regRAX);
#endif

#if defined __WIN_32__ || defined __LIN_32__
	unsigned long regEAX = 0;

	__asm
	{
		xor eax, eax
			mov eax, 01h
			cpuid
			mov regEAX, eax
	}

	*CPUfamily = (0xF & (regEAX >> 8)) + (0xFF & (regEAX >> 20));
	*CPUmodel = (0xF & (regEAX >> 4)) + ((0xF & (regEAX >> 16)) << 4);
	*CPUstepping = (0xF & regEAX);
#endif
}

