//
//  demoTools.cpp
//  EC_SDK_DEMO
//
//  Created by EC Open support team.
//  Copyright(C), 2018, Huawei Tech. Co., Ltd. ALL RIGHTS RESERVED.
//
#include "stdafx.h"
#include "demoTools.h"
#include <sstream>
#include <iomanip>
#include <regex>
#include "demo.h"
#include "demoBeforeLoginDlg.h"
#include "demoMainMenuDlg.h"
#include "HwmSdkAgent.h"

using namespace std;

HWND CTools::m_hWndCurDlg = NULL;

CTools::CTools(void)
{
}

CTools::~CTools(void)
{
}

string CTools::UNICODE2MultiByte(const wstring& wstr)
{
    std::string strRet("");
    char* result = nullptr;
    int textlen;
    textlen = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, NULL, 0, NULL, NULL);
    if (textlen <= 0) {
        return strRet;
    }
    result = new(std::nothrow) char[textlen + 1];
    if (NULL == result) {
        return strRet;
    }
    memset(result, 0, sizeof(char) * (textlen + 1));
    WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, result, textlen, NULL, NULL);
    strRet = result;
    delete[] result;
    result = nullptr;
    return strRet;
}

wstring CTools::MultiByte2UNICODE(const string& str)
{
    //确定转换为Unicode需要多少缓冲区(返回值也包含了最后一个NULL字符)。
    int nLen = MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, NULL, 0);
    if (0 >= (nLen + 1)) {
        return _T("");
    }
    wchar_t *pUnicode = new(std::nothrow)  wchar_t[nLen + 1];
    if (NULL == pUnicode) {
        return _T("");
    }

    memset(pUnicode, 0, (nLen + 1) * sizeof(wchar_t));
    ::MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, (LPWSTR)pUnicode, nLen);
    wstring  rt;
    rt = (wchar_t*)pUnicode;
    delete[] pUnicode;
    pUnicode = NULL;
    return rt;
}

wstring CTools::UTF2UNICODE(const string& str)
{
    //确定转换为Unicode需要多少缓冲区(返回值也包含了最后一个NULL字符)。
    int nLen = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, NULL, 0);
    if (0 >= (nLen + 1))
    {
        return _T("");
    }
    wchar_t *pUnicode = new(std::nothrow)  wchar_t[nLen + 1];
    if (NULL == pUnicode) {
        return _T("");
    }
    memset(pUnicode, 0, (nLen + 1)*sizeof(wchar_t));
    ::MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, (LPWSTR)pUnicode, nLen);
    wstring  rt;
    rt = (wchar_t*)pUnicode;
    delete[] pUnicode;
    pUnicode = NULL;
    return rt;
}

string CTools::UNICODE2UTF(const wstring& wstr)
{
    int iTextLen;
    // wide char to multi char
    iTextLen = WideCharToMultiByte(CP_UTF8,
        0,
        wstr.c_str(),
        -1,
        NULL,
        0,
        NULL,
        NULL);
    if (0 >= (iTextLen + 1))
    {
        return "";
    }
    char* pElementText = new(std::nothrow) char[iTextLen + 1];
    if (pElementText == nullptr) {
        return "";
    }

    memset((void*)pElementText, 0, sizeof(char) * (iTextLen + 1));
    ::WideCharToMultiByte(CP_UTF8,
        0,
        wstr.c_str(),
        -1,
        pElementText,
        iTextLen,
        NULL,
        NULL);
    string strText;
    strText = pElementText;
    delete[] pElementText;
    pElementText = NULL;
    return strText;
}

int CTools::str2num(const string& str)
{
    return atoi(str.c_str());
}

HWND CTools::str2hwnd(const string& str)
{
    HWND hwnd = 0;
    auto ret = sscanf_s(str.c_str(),"%x",&hwnd);
    if (ret != 0)
    {
        CTools::OutputRetStr("sscanf_s error");
    }
    return hwnd;
}

string CTools::num2str(int i)
{
    char str[STRING_LENGTH] = { 0 };
    sprintf_s(str, STRING_LENGTH - 1, "%d", i);
    return string(str);
}

CString CTools::getCurrentPath()
{
    TCHAR tcPath[MAX_PATH];
    TCHAR tcFilename[MAX_PATH];
    TCHAR tcDrive[_MAX_DRIVE];
    TCHAR tcDir[_MAX_DIR];
    TCHAR tcFname[_MAX_FNAME];
    TCHAR tcExt[_MAX_EXT];

    (void)GetModuleFileName(NULL, tcFilename, _MAX_PATH);

    _tsplitpath_s(tcFilename, tcDrive, tcDir, tcFname, tcExt);
    _tcscpy_s(tcPath, tcDrive);
    _tcscat_s(tcPath, tcDir);

    CString strAppPath = tcPath;
    int nPos = strAppPath.ReverseFind(_T('\\'));
    strAppPath = strAppPath.Left(nPos);
    return strAppPath;
}

void CTools::writeIniConfigParam(const CString& sectionConfig, const CString& sectionName, const CString& sectionValue)
{
    CString serverParamPath = CTools::getCurrentPath() + _T("\\demoResource\\loginCfg.ini");
    (void)WritePrivateProfileString(sectionConfig, sectionName, sectionValue, serverParamPath);
}

void CTools::getIniConfigParam(const CString& sectionConfig, const CString& sectionName, CString& sectionValue)
{
    CString serverParamPath = CTools::getCurrentPath() + _T("\\demoResource\\loginCfg.ini");
    (void)GetPrivateProfileString(sectionConfig, sectionName, _T(""), sectionValue.GetBuffer(MAX_PATH), MAX_PATH, serverParamPath);
    sectionValue.ReleaseBuffer();
}

vector<string> CTools::split(string str, const char del)
{
    stringstream ss(str);
    string tok;
    vector<string> ret;
    while (getline(ss, tok, del))
    {
        if (tok > "")
        {
            ret.push_back(tok);
        }
    }
    return ret;
}

char* CTools::MultiByte2UTF8(const string & str)
{
    int nwLen = ::MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, NULL, 0);

    wchar_t* pwBuf = new(std::nothrow) wchar_t[nwLen + 1];//一定要加1，不然会出现尾巴  
    if (pwBuf == nullptr) {
        return "";
    }

    ZeroMemory(pwBuf, nwLen * 2 + 2);

    ::MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.length(), pwBuf, nwLen);

    int nLen = ::WideCharToMultiByte(CP_UTF8, 0, pwBuf, -1, NULL, NULL, NULL, NULL);

    char* pBuf = new(std::nothrow) char[nLen + 1];
    if (pBuf == nullptr) {
        delete[] pwBuf;
        pwBuf = nullptr;
        return "";
    }
    ZeroMemory(pBuf, nLen + 1);

    ::WideCharToMultiByte(CP_UTF8, 0, pwBuf, nwLen, pBuf, nLen, NULL, NULL);

    std::string retStr(pBuf);

    delete[]pwBuf;
    delete[]pBuf;

    pwBuf = NULL;
    pBuf = NULL;

    return (char*)retStr.c_str();
}


string CTools::UTF82MultiByte(const string & str)
{
    int nwLen = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, NULL, 0);

    wchar_t * pwBuf = new(std::nothrow) wchar_t[nwLen + 1];//一定要加1，不然会出现尾巴 
    if (pwBuf == NULL)
    {
        return "";
    }
    ZeroMemory(pwBuf, nwLen * 2 + 2);

    MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), pwBuf, nwLen);

    int nLen = WideCharToMultiByte(CP_ACP, 0, pwBuf, -1, NULL, NULL, NULL, NULL);

    char* pBuf = new(std::nothrow) char[nLen + 1];
    if (pBuf == nullptr) {
        delete[] pwBuf;
        pwBuf = nullptr;
        return "";
    }
    ZeroMemory(pBuf, nLen + 1);

    WideCharToMultiByte(CP_ACP, 0, pwBuf, nwLen, pBuf, nLen, NULL, NULL);

    std::string retStr = pBuf;

    delete[]pBuf;
    delete[]pwBuf;

    pBuf = NULL;
    pwBuf = NULL;

    return retStr;
}

//16进制字符串
std::string CTools::Hex2Str(const std::vector<unsigned char>& vec)
{
    std::ostringstream oss;
    for (auto iter = vec.begin(); iter != vec.end(); ++iter) {
        oss << std::setw(2) << std::setfill('0') << std::hex;
        oss << static_cast<int>(*iter);
    }

    return oss.str();
}

//long long转字符串
string CTools::LL2S(long long data)
{
    ostringstream os;
    os << data;
    string result;
    istringstream is(os.str());
    is >> result;
    return result;
}

/**
* 初始化回调
*/
void CTools::OutputRetStr(std::string str)
{
    // 保存数据到全局缓存
    CStaticData::AddOutput(str);
    Cdemo* app = (Cdemo*)AfxGetApp();
    if (nullptr == app) {
        //窗口已经关闭
        return;
    }

    // 更新界面显示
    CdemoBeforeLoginDlg* beforeLoginDlg = dynamic_cast<CdemoBeforeLoginDlg *>(app->m_pCurDlgWnd);
    if (beforeLoginDlg != nullptr) {
        beforeLoginDlg->UpdateOutput();
    }
    demoMainMenuDlg* mainDlg = dynamic_cast<demoMainMenuDlg *>(app->m_pCurDlgWnd);
    if (mainDlg != nullptr) {
        mainDlg->UpdateOutput();
    }
}

void CTools::ShowErrMsg(int ret, const char * reason)
{
    if (ret == S_OK)
    {
        return;
    }

    std::string showStr;
    
    std::string errMsg = GetErrMsg(ret);
    if (!errMsg.empty())
    {
        showStr += errMsg + "\n";
    }
    showStr += UNICODE2UTF(L"错误码：") + std::to_string(ret) + "\n";
    std::string reasonStr = reason != nullptr ? reason : "";
    showStr += UNICODE2UTF(L"错误描述：") + reasonStr;

    AfxMessageBox(UTF2UNICODE(showStr).c_str());
}

std::string CTools::GetErrMsg(int ret)
{
    hwmsdkagent::HwmErrorMessageInfo errorMsg{};
    hwmsdkagent::GetErrorMessage(ret, &errorMsg);
    return errorMsg.errorMessage;
}

bool CTools::IsPhoneNumberString(const std::string& phoneNumber)
{
    std::regex pattern(R"(^(\+86)?1[3-9]\d{9}$)");
    return std::regex_match(phoneNumber, pattern);
}

void CTools::GetEditValue(char * dst, unsigned int size, const CEdit & edit)
{
    CString input;
    edit.GetWindowText(input);
    const auto value = CTools::UNICODE2UTF(input.GetString());
    const auto ret = strcpy_s(dst, size, value.c_str());
    if (ret != 0)
    {
        AfxMessageBox(_T("string copy error"));
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////
string CStaticData::output = "";

CStaticData::CStaticData(void)
{
}

CStaticData::~CStaticData(void)
{
}
