//
// Copyright (c) 2014 ANSCENTER. All rights reserved.
//

#include "precomp.h"

#include <list>
#include <string>

#ifdef _WIN32
#include "wmihelper.h"
#endif

#include "anslicensing.h"
#include "uniconv.h"
#include "except.h"
#include "hwid.h"
#include "base64.h"

class KeyHelperImpl {

friend class KeyHelperT<char>;
friend class KeyHelperT<wchar_t>;

private:
	static const char * GetCurrentHardwareId()
	{
		return HardwareId::GetCurrentHardwareId();
	}

	static bool MatchCurrentHardwareId(const char * hwid)
	{
		return HardwareId::MatchCurrentHardwareId(hwid);
	}

	static bool DetectClockManipulation(int year, int month, int day)
	{
#ifdef _WIN32
		FILETIME thresholdTime;
		SYSTEMTIME st;
		TCHAR path[MAX_PATH];

		ZeroMemory(&st, sizeof(st));

		st.wYear = year;
		st.wMonth = month;
		st.wDay = day;
		st.wHour = 23;
		st.wMinute = 59;
		st.wSecond = 59;

		if (!SystemTimeToFileTime(&st, &thresholdTime))
			return false;

		if (GetTempPath(MAX_PATH, path) > 0)
		{
			_tcsncat_s<MAX_PATH>(path, "*.*", _TRUNCATE);

			WIN32_FIND_DATA findData;
			
			HANDLE findHandle = FindFirstFile(path, &findData);
			if (findHandle != INVALID_HANDLE_VALUE)
			{
				while (FindNextFile(findHandle, &findData))
				{
					if (CompareFileTime(&findData.ftLastWriteTime, &thresholdTime) > 0)
						return true;
				}

				FindClose(findHandle);
			}
		}

		WmiHelper wmi;
		list<string> propList;

		char dmtfTime[100];
	    char query[MAX_PATH];

		_snprintf_s(query, MAX_PATH, _TRUNCATE, "SELECT EventIdentifier FROM Win32_NTLogEvent WHERE LogFile='system' AND TimeGenerated > '%04d%02d%02d000000.000000-000'", st.wYear, st.wMonth, st.wDay);

		wmi.GetPropertyList(query, "EventIdentifier", &propList);

	    if (propList.size() > 0)
			return true;
#endif

		return false;
	}
};

namespace ANSCENTER
{
	namespace Licensing
	{

		template<>
		const char * KeyHelperT<char>::GetCurrentHardwareId()
		{
			return KeyHelperImpl::GetCurrentHardwareId();
		}

		template<>
		const wchar_t * KeyHelperT<wchar_t>::GetCurrentHardwareId()
		{
			static wstring wstr1;
			
			wstr1 = s2w(KeyHelperImpl::GetCurrentHardwareId());
			return wstr1.c_str();
		}

		template<>
		bool KeyHelperT<char>::MatchCurrentHardwareId(const char * hwid)
		{
			return KeyHelperImpl::MatchCurrentHardwareId(hwid);
		}

		template<>
		bool KeyHelperT<wchar_t>::MatchCurrentHardwareId(const wchar_t * hwid)
		{		
			return KeyHelperImpl::MatchCurrentHardwareId(w2s(hwid).c_str());
		}

		template<>
		bool KeyHelperT<char>::DetectClockManipulation(int thresholdYear, int thresholdMonth, int thresholdDay)
		{
			return KeyHelperImpl::DetectClockManipulation(thresholdYear, thresholdMonth, thresholdDay);
		}

		template<>
		bool KeyHelperT<wchar_t>::DetectClockManipulation(int thresholdYear, int thresholdMonth, int thresholdDay)
		{
			return KeyHelperImpl::DetectClockManipulation(thresholdYear, thresholdMonth, thresholdDay);
		}
	};
};

namespace ANSCENTER
{
	namespace Licensing
	{
			 const char* ANSUtility::WString2String(const wchar_t * inputString) {
				string result = w2s(inputString);
				return result.c_str();

			}
			 const wchar_t* ANSUtility::String2WString(const char* inputString) {
				wstring result = s2w(inputString);
				return result.c_str();
			}

			 const char* ANSUtility::EncodeBase64Utility(unsigned char* buf, int len, bool padding) {
				 BASE64 base64;
				 string result= base64.encode(buf, len,padding);
				 return result.c_str();
			 }

			const char* ANSUtility::DecodeBase64Utility(const char* input, int len, int* outlen) {
				 BASE64 base64;
				 vector<unsigned char> result = base64.decode(input, len, nullptr);
				 string str(result.begin(), result.end());
				 return str.c_str();
			 }


	
	}
}

