#pragma once
#include <utility>
#include <limits.h>
#include <vector>
#include <iostream>
#include <ole2.h> // OLE2 Definitions
#include <atlsafe.h>

template <typename T>
void convertTypeToVariant(T d1, VARIANT& d1_var) {

}

template<> inline void convertTypeToVariant(double d1, VARIANT& d1_var) {
	d1_var.vt = VT_R8;
	d1_var.dblVal = d1;
}

template<> inline void convertTypeToVariant(int d1, VARIANT& d1_var) {
	d1_var.vt = VT_UI2;
	d1_var.iVal = d1;
}

template<> inline void convertTypeToVariant(float d1, VARIANT& d1_var) {
	d1_var.vt = VT_R4;
	d1_var.fltVal = d1;
}

template<> inline void convertTypeToVariant(unsigned char d1, VARIANT& d1_var) {
	d1_var.vt = VT_UI1;
	d1_var.bVal = d1;
}


HRESULT AutoWrap(int autoType, VARIANT *pvResult, IDispatch *pDisp, LPOLESTR ptName, int cArgs...);
VARIANT DCOMCallMethod(IDispatch *p, const wchar_t* cmd);
void DCOMSetProperty(IDispatch *p, const wchar_t* cmd, int val);

VARIANT DCOMGetProperty(IDispatch *p, const wchar_t* property);
VARIANT DCOMGetProperty(IDispatch *p, const wchar_t* property, int i);


VARIANT DCOMCallMethod(IDispatch *p, const wchar_t* cmd, wchar_t* val);
VARIANT DCOMCallMethod(IDispatch *p, const wchar_t* cmd, VARIANT s);

template <typename T>
VARIANT DCOMCallMethod(IDispatch* p, const wchar_t* cmd, T i) {
	try {
		VARIANT x;
		VARIANT d1_var;

		convertTypeToVariant(i, d1_var);

		AutoWrap(DISPATCH_METHOD, &x, p, (wchar_t*)cmd, 1, d1_var);
		return x;
	}
	catch (int e) {
		throw e;
	}
}

template<> inline VARIANT DCOMCallMethod(IDispatch* p, const wchar_t* cmd, SAFEARRAY* s) {
	try {
		VARIANT x;
		VARIANT s_var;
		s_var.vt = VT_ARRAY | VT_I4;
		s_var.parray = s;
		AutoWrap(DISPATCH_METHOD, &x, p, (wchar_t*)cmd, 1, s_var);
		return x;
	}
	catch (int e) {
		throw e;
	}
}

template<> inline VARIANT DCOMCallMethod(IDispatch* p, const wchar_t* cmd, CComSafeArray<int32_t> s) {
	return DCOMCallMethod(p, cmd, (SAFEARRAY*)s);
}

template <typename T>
VARIANT DCOMCallMethod(IDispatch* p, const wchar_t* cmd, T d1, double d2) {
	try {
		VARIANT x;
		VARIANT d1_var;

		convertTypeToVariant(d1, d1_var);

		VARIANT d2_var;
		d2_var.vt = VT_R8;
		d2_var.dblVal = d2;

		AutoWrap(DISPATCH_METHOD, &x, p, (wchar_t*)cmd, 2, d1_var, d2_var);
		return x;
	}
	catch (int e) {
		throw e;
	}
}
