//---------------------------------------------------------------------------
//#pragma hdrstop
//#include "stdafx.h"
//---------------------------------------------------------------------------
#include "ShlObj.h"
#include "WTools.h"
#include "stdTools.h"

#include <sstream>
//#include <WinBase.h>
#include <atlbase.h>

//---------------------------------------------------------------------------
int getIntVal(VARIANT *pvarPropVal)
{
	if(pvarPropVal->vt==VT_BOOL) return pvarPropVal->boolVal==0 ? 0 : 1; else
	if(pvarPropVal->vt==VT_I2)   return pvarPropVal->bVal; else
	if(pvarPropVal->vt==VT_I4)   return pvarPropVal->intVal; else
	if(pvarPropVal->vt==VT_R4)   return (int)pvarPropVal->fltVal; else
	if(pvarPropVal->vt==VT_R8)   return (int)pvarPropVal->dblVal; else
	if(pvarPropVal->vt==VT_BSTR) return Utility::fromString<int>(getSTDStr(pvarPropVal->bstrVal)); else
		return 0;
}
//---------------------------------------------------------------------------
char getCharVal(VARIANT *pvarPropVal)
{
	if(pvarPropVal->vt==VT_BOOL) return pvarPropVal->boolVal==0 ? 0 : 1; else
	if(pvarPropVal->vt==VT_I2)   return pvarPropVal->bVal; else
	if(pvarPropVal->vt==VT_I4)   return pvarPropVal->intVal; else
	if(pvarPropVal->vt==VT_R4)   return (int)pvarPropVal->fltVal; else
	if(pvarPropVal->vt==VT_R8)   return (int)pvarPropVal->dblVal; else
	if(pvarPropVal->vt==VT_BSTR)
	{
		std::string str = getSTDStr(pvarPropVal->bstrVal);
		if(str.size()>0) return str[0]; else return 0;
	}else
		return 0;
}
//---------------------------------------------------------------------------
bool getBoolVal(VARIANT *pvarPropVal)
{
	if(pvarPropVal->vt==VT_BOOL) return pvarPropVal->boolVal==0 ? false : true; else
	if(pvarPropVal->vt==VT_I2)   return pvarPropVal->bVal==0 ? false : true; else
	if(pvarPropVal->vt==VT_I4)   return pvarPropVal->intVal==0 ? false : true; else
	if(pvarPropVal->vt==VT_R4)   return pvarPropVal->fltVal==0 ? false : true; else
	if(pvarPropVal->vt==VT_R8)   return pvarPropVal->dblVal==0 ? false : true; else
	if(pvarPropVal->vt==VT_BSTR)
	{
		std::string str = getSTDStr(pvarPropVal->bstrVal);
		if(Utility::lowerCaseENG(str)=="true" || str=="1")
		return true; else return false;
	}
		return false;
}
//---------------------------------------------------------------------------
float getFloatVal(VARIANT *pvarPropVal)
{
	if(pvarPropVal->vt==VT_BOOL) return pvarPropVal->boolVal==0 ? 0.0f : 1.0f; else
	if(pvarPropVal->vt==VT_I2)   return pvarPropVal->bVal; else
	if(pvarPropVal->vt==VT_I4)   return (float)pvarPropVal->intVal; else
	if(pvarPropVal->vt==VT_R4)   return pvarPropVal->fltVal; else
	if(pvarPropVal->vt==VT_R8)   return (float)pvarPropVal->dblVal; else
	if(pvarPropVal->vt==VT_BSTR) return Utility::fromString<float>(getSTDStr(pvarPropVal->bstrVal)); else
		return 0;
}
//---------------------------------------------------------------------------
double getDoubleVal(VARIANT *pvarPropVal)
{
	if(pvarPropVal->vt==VT_BOOL) return pvarPropVal->boolVal==0 ? 0 : 1; else
	if(pvarPropVal->vt==VT_I2)   return pvarPropVal->bVal; else
	if(pvarPropVal->vt==VT_I4)   return (double)pvarPropVal->intVal; else
	if(pvarPropVal->vt==VT_R4)   return pvarPropVal->fltVal; else
	if(pvarPropVal->vt==VT_R8)   return (double)pvarPropVal->dblVal; else
	if(pvarPropVal->vt==VT_BSTR) return Utility::fromString<float>(getSTDStr(pvarPropVal->bstrVal)); else
		return 0;
}
//---------------------------------------------------------------------------
//Преобразование типов если нужно
std::string getStringVal(VARIANT *pvarPropVal)
{
	if(pvarPropVal->vt==VT_BOOL) return Utility::IntToStdStr(pvarPropVal->boolVal==0 ? 0 : 1); else
	if(pvarPropVal->vt==VT_I2) return Utility::IntToStdStr(pvarPropVal->bVal); else
	if(pvarPropVal->vt==VT_I4) return Utility::IntToStdStr(pvarPropVal->intVal); else
	if(pvarPropVal->vt==VT_R4) return Utility::FloatToStdStr(pvarPropVal->fltVal); else
	if(pvarPropVal->vt==VT_R8) return Utility::FloatToStdStr(pvarPropVal->dblVal); else
	if(pvarPropVal->vt==VT_BSTR) return getSTDStr(pvarPropVal->bstrVal); else
	return "";
}
//---------------------------------------------------------------------------
std::wstring getWStringVal(VARIANT *pvarPropVal)
{
	std::wstring result;
	if (pvarPropVal->vt == VT_BSTR) {
		result=getSTDWStr(pvarPropVal->bstrVal);
	}
	else {
		std::string str = getStringVal(pvarPropVal);
		result = Utility::StringToWString(str, std::locale(""));
	}
	return result;
}
//---------------------------------------------------------------------------
//#pragma package(smart_init)
//---------------------------------------------------------------------------
BSTR stdStrToBSTR(const std::string& s)
{
	BSTR str=NULL;
#if defined( _ATL )
	str=CComBSTR(s.c_str()).Detach();
#endif
	return str;
}
//---------------------------------------------------------------------------
BSTR stdWStrToBSTR(const std::wstring& s)
{
	BSTR str=NULL;
#if defined( _ATL )
	return CComBSTR(s.c_str()).Detach();
#endif
	return str;
}
//---------------------------------------------------------------------------
/*std::string from_variant(VARIANT& vt)
{
_bstr_t bs(vt);
return std::string(static_cast<const char*>(bs));
}*/
//---------------------------------------------------------------------------
///Преобразование из Unicode BSTR строки в ANSI строку std::string
std::string getSTDStr(const BSTR& unicodestr)
{
	std::string str="";
	char *ansistr;
	int lenW = ::SysStringLen(unicodestr);
	int lenA = ::WideCharToMultiByte(CP_ACP, 0, unicodestr, lenW, 0, 0, NULL, NULL);
	if (lenA > 0)
	{
		ansistr = new char[lenA + 1]; // allocate a final null terminator as well
		::WideCharToMultiByte(CP_ACP, 0, unicodestr, lenW, ansistr, lenA, NULL, NULL);
		ansistr[lenA] = 0; // Set the null terminator yourself
		str=ansistr;
		delete[] ansistr;
	}
	return str;
}
//---------------------------------------------------------------------------
std::wstring getSTDWStr(const BSTR& unicodestr)
{
	if(unicodestr==NULL) return L"";
	return unicodestr;
}
//---------------------------------------------------------------------------
//Сохранить параметр в ini файл
bool IniWriteW(std::wstring filename,std::wstring section,std::wstring key,std::wstring data)
{
	std::wstring str= Utility::BeforeWLast(filename,L'\\');
	CreateDirectory(str.c_str(), NULL); //Пробуем создать папку

	return WritePrivateProfileString(
		(LPCWSTR)section.c_str(),
		(LPCWSTR)key.c_str(),
		(LPCWSTR)data.c_str(),
		(LPCWSTR)filename.c_str()
	)==TRUE;
}
//---------------------------------------------------------------------------
std::wstring IniReadW(std::wstring filename,std::wstring section,std::wstring key)
{
	wchar_t *out = new wchar_t[512];
	GetPrivateProfileString(
		(LPCWSTR)section.c_str(),
		(LPCWSTR)key.c_str(),
		NULL,
		out,
		200,
		(LPCWSTR)filename.c_str()
	);
	return out;
}
//---------------------------------------------------------------------------
//Путь к "Application Data" для всех пользователей
std::wstring getCommonAppPathW()
{
	wchar_t szPath[MAX_PATH];
	SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, 0, szPath);
	return  szPath;
}
//---------------------------------------------------------------------------
//Путь к "Application Data" для всех пользователей
std::string getCommonAppPathA()
{
	char szPath[MAX_PATH];
	SHGetFolderPathA(NULL, CSIDL_COMMON_APPDATA, NULL, 0, szPath);
	return  szPath;
}
//---------------------------------------------------------------------------
//Путь к "Application Data" для текущего пользователя
/*std::wstring getDefaultAppPathW()
{
	wchar_t szPath[MAX_PATH];
	SHGetFolderPath(NULL, CSIDL_DEFAULT_APPDATA, NULL, 0, szPath);
	return  szPath;
}*/
//---------------------------------------------------------------------------
//Путь к "Application Data" пользователя
std::wstring getAppDataPathW()
{
	wchar_t szPath[MAX_PATH];
	SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, szPath);
	return  szPath;
}
//---------------------------------------------------------------------------
//Путь к "Application Data" пользователя
std::string getAppDataPathA()
{
	char szPath[MAX_PATH];
	SHGetFolderPathA(NULL, CSIDL_APPDATA, NULL, 0, szPath);
	return  szPath;
}
//---------------------------------------------------------------------------
//Выключить компьютер
bool shoot(bool reboot, bool force)
{
/*
	OSVERSIONINFO ver;
	ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
	GetVersionEx(&ver);
	if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) // в семействе NT для выключения необходимо иметь привилегию SE_SHUTDOWN_NAME
	{
		HANDLE hToken;
		TOKEN_PRIVILEGES* NewState;
		OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken);
		NewState=(TOKEN_PRIVILEGES*)malloc(sizeof(TOKEN_PRIVILEGES) + sizeof (LUID_AND_ATTRIBUTES));
		NewState->PrivilegeCount = 1;
		LookupPrivilegeValue(NULL,SE_SHUTDOWN_NAME,&NewState->Privileges[0].Luid);
		NewState->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
		AdjustTokenPrivileges(hToken, FALSE, NewState, NULL, NULL,NULL);
		free(NewState);
		CloseHandle(hToken);
	}
	UINT mode = 0;
	if (reboot)
		mode += EWX_REBOOT;
	else
		mode += EWX_POWEROFF;
	if (force) mode += EWX_FORCE;
	ExitWindowsEx(mode ,0);
	*/
	return true;
}
//---------------------------------------------------------------------------
std::string getCurrentFilePath()
{
	char path[MAX_PATH];
	GetModuleFileNameA(NULL, path, 2048);
	return path;
/*
	char path[MAX_PATH];
	HMODULE hm = NULL;

	if (!GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR) &localFunc, &hm))
	{
		int ret = GetLastError();
		fprintf(stderr, "GetModuleHandle returned %d\n", ret);
	}
	GetModuleFileNameA(hm, path, sizeof(path));
*/
}
//---------------------------------------------------------------------------
//Прочитать версию файла
std::string getFileVersion( std::wstring path )
{
	DWORD dwHandle, sz = GetFileVersionInfoSizeW( path.c_str(), & dwHandle );
    if ( 0 == sz )
    {
        return "";
    }
    std::vector< unsigned char > buf( sz );
    if ( !GetFileVersionInfoW( path.c_str(), dwHandle, sz, & buf[ 0 ] ) )
    {
        return "";
    }
    VS_FIXEDFILEINFO * pvi;
    sz = sizeof( VS_FIXEDFILEINFO );
    if ( !VerQueryValueA( & buf[ 0 ], "\\", (LPVOID*)&pvi, (unsigned int*)&sz ) )
    {
        return "";
    }
    char ver[ 142 ];
    sprintf( ver, "%d.%d.%d.%d"
            , pvi->dwProductVersionMS >> 16
            , pvi->dwFileVersionMS & 0xFFFF
            , pvi->dwFileVersionLS >> 16
            , pvi->dwFileVersionLS & 0xFFFF
            );
    return ver;

}

