// This file implements the IOleCommandTarget Interface and Gateway for Python.
// Generated by makegw.py

#include "axcontrol_pch.h"
#include "PyIOleCommandTarget.h"

static BOOL FillOLECMDsWithSequence(OLECMD *pCmds, UINT ncmds, PyObject *obCmds)
{
	for (UINT i=0;i<ncmds;i++) {
		OLECMD *pThis = pCmds + i;
		PyObject *sub = PySequence_GetItem(obCmds, i);
		if (!sub)
			return FALSE;
		if (!PyArg_ParseTuple(sub, "ii",  &pThis->cmdID, &pThis->cmdf)) {
			PyErr_Format(PyExc_TypeError, "Element %d of command buffer was not a tuple of 2 integers", i);
			Py_DECREF(sub);
			return FALSE;
		}
		Py_DECREF(sub);
	}
	return TRUE;
}

// @doc - This file contains autoduck documentation
// ---------------------------------------------------
//
// Interface Implementation

PyIOleCommandTarget::PyIOleCommandTarget(IUnknown *pdisp):
	PyIUnknown(pdisp)
{
	ob_type = &type;
}

PyIOleCommandTarget::~PyIOleCommandTarget()
{
}

/* static */ IOleCommandTarget *PyIOleCommandTarget::GetI(PyObject *self)
{
	return (IOleCommandTarget *)PyIUnknown::GetI(self);
}

// @pymethod |PyIOleCommandTarget|QueryStatus|Description of QueryStatus.
PyObject *PyIOleCommandTarget::QueryStatus(PyObject *self, PyObject *args)
{
	PyObject *ret = NULL;
	PyObject *obGUID, *obCmds;
	IOleCommandTarget *pIOCT = GetI(self);
	OLECMD *pCmds = NULL;
	OLECMDTEXT *retText = NULL;
	if ( pIOCT == NULL )
		return NULL;
	if (!PyArg_ParseTuple(args, "OO", &obGUID, &obCmds))
		return NULL;

	GUID guid;
	GUID *pguid;
	if (obGUID == Py_None) {
		pguid = NULL;
	} else {
		if (!PyWinObject_AsIID(obGUID, &guid))
			return FALSE;
		pguid = &guid;
	}
	if (!PySequence_Check(obCmds))
		return PyErr_Format(PyExc_TypeError, "cmds must be a sequence");

	int ncmds = PySequence_Length(obCmds);
	HRESULT hr;
	// From here, exit via 'goto done'
	const unsigned cbCmdText = 1024;
	retText = (OLECMDTEXT *)malloc(cbCmdText);
	if (!retText) {
		PyErr_NoMemory();
		goto done;
	}
	retText->cwBuf = (cbCmdText - sizeof(OLECMDTEXT)) / sizeof(WCHAR);

	pCmds = (OLECMD *)malloc(ncmds * sizeof(OLECMD));
	if (!pCmds) {
		PyErr_NoMemory();
		goto done;
	}
	if (!FillOLECMDsWithSequence(pCmds, ncmds, obCmds))
		goto done;
	{ // scope to prevent goto warning.
	PY_INTERFACE_PRECALL;
	hr = pIOCT->QueryStatus( pguid, ncmds, pCmds, retText );
	PY_INTERFACE_POSTCALL;
	}

	if ( FAILED(hr) ) {
		PyCom_BuildPyException(hr, pIOCT, IID_IOleCommandTarget );
		goto done;
	}
	ret = Py_BuildValue("iN", retText->cmdtextf,
			    PyWinObject_FromWCHAR(retText->rgwz));
done:
	if (retText)
		free(retText);
	if (pCmds)
		free(pCmds);
	return ret;
}

// @pymethod |PyIOleCommandTarget|Exec|Description of Exec.
PyObject *PyIOleCommandTarget::Exec(PyObject *self, PyObject *args)
{
	PyObject *ret;
	int cmdid, cmdopt;
	PyObject *obVar;
	PyObject *obGUID;
	VARIANT varIn, varOut;
	IOleCommandTarget *pIOCT = GetI(self);
	if ( pIOCT == NULL )
		return NULL;
	if (!PyArg_ParseTuple(args, "OiiO", &obGUID, &cmdid, &cmdopt, &obVar))
		return NULL;

	GUID guid;
	GUID *pguid;
	if (obGUID == Py_None) {
		pguid = NULL;
	} else {
		if (!PyWinObject_AsIID(obGUID, &guid))
			return FALSE;
		pguid = &guid;
	}
	VariantInit(&varIn);
	VariantInit(&varOut);
	if (!PyCom_VariantFromPyObject(obVar, &varIn))
		return NULL;

	HRESULT hr;
	PY_INTERFACE_PRECALL;
	hr = pIOCT->Exec( pguid, cmdid, cmdopt, &varIn, &varOut);
	PY_INTERFACE_POSTCALL;
	
	VariantClear(&varIn);

	if ( FAILED(hr) ) {
		PyCom_BuildPyException(hr, pIOCT, IID_IOleCommandTarget );
		ret = NULL;
	} else {
		ret = PyCom_PyObjectFromVariant(&varOut);
	}
	VariantClear(&varOut);
	return ret;
}

// @object PyIOleCommandTarget|Description of the interface
static struct PyMethodDef PyIOleCommandTarget_methods[] =
{
	{ "QueryStatus", PyIOleCommandTarget::QueryStatus, 1 }, // @pymeth QueryStatus|Description of QueryStatus
	{ "Exec", PyIOleCommandTarget::Exec, 1 }, // @pymeth Exec|Description of Exec
	{ NULL }
};

PyComTypeObject PyIOleCommandTarget::type("PyIOleCommandTarget",
		&PyIUnknown::type,
		sizeof(PyIOleCommandTarget),
		PyIOleCommandTarget_methods,
		GET_PYCOM_CTOR(PyIOleCommandTarget));
// ---------------------------------------------------
//
// Gateway Implementation
STDMETHODIMP PyGOleCommandTarget::QueryStatus(
		/* [unique][in] */ const GUID * pguidCmdGroup,
		/* [in] */ ULONG cCmds,
		/* [out][in][size_is] */ OLECMD prgCmds[],
		/* [unique][out][in] */ OLECMDTEXT * pCmdText)
{
	PY_GATEWAY_METHOD;
	PyObject *obGUID;
	if (pguidCmdGroup == NULL) {
		obGUID = Py_None;
		Py_INCREF(obGUID);
	} else {
		obGUID = PyWinObject_FromIID(*pguidCmdGroup);
	}
	PyObject *cmds = PyList_New(cCmds);
	if (!cmds) {
		Py_DECREF(obGUID);
		MAKE_PYCOM_GATEWAY_FAILURE_CODE("QueryStatus");
	}
	for (ULONG i=0;i<cCmds;i++) {
		PyList_SET_ITEM(cmds, i,
				Py_BuildValue("ll", prgCmds[i].cmdID, prgCmds[i].cmdf));
	}
	PyObject *obText;
	if (!pCmdText) {
		obText = Py_None;
		Py_INCREF(Py_None);
	} else
		obText = PyInt_FromLong(pCmdText->cmdtextf);
	PyObject *result;
	HRESULT hr=InvokeViaPolicy("QueryStatus", &result, "NNN", obGUID, cmds, obText);
	if (FAILED(hr)) return hr;

	BOOL ok = PyArg_ParseTuple(result, "OO", &cmds, &obText);
	if (ok) {
		if (pCmdText == NULL) {
			if (obText != Py_None) {
				PyErr_SetString(PyExc_ValueError,
						"String value returned but caller didn't request it (check the 3rd param!)");
				ok = FALSE;
			}
		} else {
			PyWin_AutoFreeBstr tempString;
			ok = PyWinObject_AsAutoFreeBstr(obText, &tempString);
			if (ok) {
				UINT strLen = SysStringLen(tempString);
				UINT nwrite = min(strLen, pCmdText->cwBuf);
				wcsncpy(pCmdText->rgwz, (WCHAR *)(BSTR)tempString,
					nwrite);
				pCmdText->cwActual = nwrite;
			}
		}
	}
	if (ok) {
		if (!PySequence_Check(cmds)) {
			PyErr_SetString(PyExc_TypeError, "OLECMD objects must be a sequence");
			ok = FALSE;
		}
		if (ok && (UINT)PySequence_Length(cmds) != cCmds) {
			PyErr_Format(PyExc_ValueError, "Sequence must have %d items (got %d)",
				     cCmds, PySequence_Length(cmds));
			ok = FALSE;
			
		}
		if (ok)
			ok = FillOLECMDsWithSequence(prgCmds, cCmds, cmds);
	}
	Py_DECREF(result);
	if (!ok)
		hr = MAKE_PYCOM_GATEWAY_FAILURE_CODE("QueryStatus");
	return hr;
}

STDMETHODIMP PyGOleCommandTarget::Exec(
		/* [unique][in] */ const GUID * pguidCmdGroup,
		/* [in] */ DWORD nCmdID,
		/* [in] */ DWORD nCmdexecopt,
		/* [unique][in] */ VARIANT * pvaIn,
		/* [unique][out][in] */ VARIANT * pvaOut)
{
	PY_GATEWAY_METHOD;
	PyObject *obGUID;
	if (pguidCmdGroup == NULL) {
		obGUID = Py_None;
		Py_INCREF(obGUID);
	} else {
		obGUID = PyWinObject_FromIID(*pguidCmdGroup);
	}
	PyObject *obpvaIn = PyCom_PyObjectFromVariant(pvaIn);
	PyObject *result;
	HRESULT hr=InvokeViaPolicy("Exec", &result, "NllN", obGUID, nCmdID, nCmdexecopt, obpvaIn);
	if (FAILED(hr)) return hr;
	hr = pvaOut ? PyCom_VariantFromPyObject(result, pvaOut) : S_OK;
	Py_DECREF(result);
	return hr;
}

