#include "utility.h"
#include <stdio.h> 
#include <stdlib.h> 
#include <stdarg.h> 
#include <iostream>
#include <string.h>
#include <chrono>

#ifdef WIN32
#include <Windows.h>
#include <ctime>
#else
#include <iconv.h>
#include <sys/time.h>
#include <unistd.h>
#endif

//函数名: GetProcDir() 
//功  能: 获取当前程序的路径 
std::string GetProcDir()
{
    std::string strDir;
#ifdef WIN32
    int curPos;
    char pathBuf[MAX_PATH] = { 0 };
    ::GetModuleFileNameA(NULL, pathBuf, MAX_PATH);

    curPos = strlen(pathBuf) - 1;
    while('\\' != pathBuf[curPos])
    {
        curPos--;
    }

    curPos++;
    pathBuf[curPos] = '\0';
    strDir=pathBuf;
#else    
    char szBuffer[256]; 
    int npos = 0; 
    npos = readlink( "/proc/self/exe", szBuffer, 256 ); 
    if ( npos < 0 || npos >= 256 ) 
    { 
        printf( "readlink failed.\n" ); 
        return strDir; 
    } 
    szBuffer[npos] = '\0'; 
    char *ptr = NULL;  
    char c = '/';      
    ptr = strrchr(szBuffer,c);  
    if(ptr != NULL)
        *(ptr +1) = 0;
    strDir = szBuffer;
#endif
    return strDir;
}

int charset_convert(const char* charset_from, const char* charset_to, const std::string& string_from, std::string& string_to)
{
#ifdef WIN32
#else
    iconv_t cd = iconv_open(charset_to, charset_from);
    if (!cd)
    {
        return -1;
    }

    string_to = "";
    int ret = 0;
    size_t inbytes = string_from.size();
    char* inbuf = const_cast<char*>(string_from.c_str());
    while (inbytes > 0)
    {
        char buffer[2048] = {0};
        char *outbuf = buffer;
        size_t outbytes = sizeof(buffer) - 1;
        ret = iconv(cd, &inbuf, &inbytes, &outbuf, &outbytes);
        if (ret == 0 || errno == E2BIG)
        {
            string_to.append(buffer);
        }
        else
        {
            break;
        }
    }
    ret = iconv_close(cd);
    if (inbytes != 0 || ret != 0)
    {
        return -1;
    }
#endif
    return 0;
}

#ifdef WIN32
std::string GBKToUTF8(const std::string& strGBK)
{
    std::string strOutUTF8;
    WCHAR* str1;
    int n = MultiByteToWideChar(CP_ACP, 0, strGBK.c_str(), -1, NULL, 0);
    str1 = new WCHAR[n];
    MultiByteToWideChar(CP_ACP, 0, strGBK.c_str(), -1, str1, n);
    n = WideCharToMultiByte(CP_UTF8, 0, str1, -1, NULL, 0, NULL, NULL);
    char * str2 = new char[n];
    WideCharToMultiByte(CP_UTF8, 0, str1, -1, str2, n, NULL, NULL);
    strOutUTF8 = str2;
    delete[]str1;
    delete[]str2;
    return strOutUTF8;
}

std::string UTF8ToGBK(const std::string& strUTF8)
{
    std::string strOutGBK;
    int len = MultiByteToWideChar(CP_UTF8, 0, strUTF8.data(), -1, NULL, 0);
    wchar_t* wstr = new wchar_t[len + 1];
    memset(wstr, 0, len + 1);
    MultiByteToWideChar(CP_UTF8, 0, strUTF8.data(), -1, wstr, len);
    len = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
    char* str = new char[len + 1];
    memset(str, 0, len + 1);
    WideCharToMultiByte(CP_ACP, 0, wstr, -1, str, len, NULL, NULL);
    strOutGBK = str;
    delete[] wstr;
    delete[] str;
    return strOutGBK;
}
#endif

//GB2312码转为utf8码
std::string charset_g2u(const std::string& gb2312)
{
    std::string utf8;
#ifdef WIN32
    utf8 = GBKToUTF8(gb2312);
#else
    charset_convert("gb2312", "utf-8", gb2312, utf8);
#endif
    //std::cout<<"convert res:"<<i<<std::endl;
    return utf8;
}

//utf8码转为GB2312码
std::string charset_u2g(const std::string& utf8)
{
    std::string gb2312;
#ifdef WIN32
    gb2312 = UTF8ToGBK(utf8);
#else
    charset_convert( "utf-8","gb2312", utf8, gb2312);
#endif
    //std::cout<<"convert res:"<<i<<std::endl;
    return gb2312;
}

//获取时间戳（毫秒）
int64_t timestamps_milliseconds()
{
#ifdef WIN32
    std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds> tp = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now());
    auto tmp = std::chrono::duration_cast<std::chrono::milliseconds>(tp.time_since_epoch());
    return tmp.count();
#else
   struct timeval tv;    
   gettimeofday(&tv,NULL);
   return (int64_t)tv.tv_sec*1000 + tv.tv_usec/1000;
#endif
} 
//获取时间戳（秒）
int64_t timestamp_seconds()
{
#ifdef WIN32
    std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds> tp = std::chrono::time_point_cast<std::chrono::seconds>(std::chrono::system_clock::now());
    auto tmp = std::chrono::duration_cast<std::chrono::seconds>(tp.time_since_epoch());
    return tmp.count();
#else
   struct timeval tv;    
   gettimeofday(&tv,NULL);
   return tv.tv_sec; 
#endif
}

std::string getdatetime(int64_t timestamp)
{
    std::string strDate;
    int64_t milli = timestamp+ (int64_t)8*60*60*1000;//此处转化为东八区北京时间，如果是其它时区需要按需求修改
    auto mTime = std::chrono::milliseconds(milli);
    auto tp=std::chrono::time_point<std::chrono::system_clock,std::chrono::milliseconds>(mTime);
    auto tt = std::chrono::system_clock::to_time_t(tp);
    std::tm* now = std::gmtime(&tt);
    char datetime[64];
    sprintf(datetime,"%4d%02d%02d%02d%02d%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday,now->tm_hour,now->tm_min,now->tm_sec);
    strDate=datetime;
    return strDate;
}

void os_sleep(int seconds)
{
#ifdef WIN32
    Sleep(seconds*1000);
#else
    sleep(seconds);
#endif
}
