#include "stdafx.h"

#include "Strawberry.h"		//CMultiDocTemplate*	pDocTemplate1
							//DWORD					status_fl		(from "HeadFunc.h")
#include "StrawberryDoc.h"	//CStrawberryDoc*		m_pOutputDoc 

#include "StrawberrySvr.h"

//static members
CStrawberrySvr* CStrawberrySvr::m_obj=NULL;


// ctor/dtor
CStrawberrySvr::CStrawberrySvr()
{
	m_pUnkMarshaler = NULL;
}

HRESULT CStrawberrySvr::FinalConstruct()
{
	HRESULT hr = CoCreateFreeThreadedMarshaler( GetControllingUnknown(), &m_pUnkMarshaler.p);
	if(FAILED(hr)) return hr;
	
	if(status_fl&64)//Run Directly;
	{
		m_pOutputDoc=(CStrawberryDoc*)pDocTemplate1->OpenDocumentFile(NULL);
    m_obj = this;
	}
	else
		m_obj = NULL;

	return hr;
}

void CStrawberrySvr::FinalRelease()
{
	m_pUnkMarshaler.Release();

	if(!(status_fl&64))return;//not Run Directly;

	//the hard way to do PostQuitMessage 
	AFX_MODULE_STATE* pState = AfxGetAppModuleState();
	if(!pState){ ASSERT(FALSE && _T("Cant get AppModuleState"));return;}

	CWinThread* pThread = pState->m_pCurrentWinApp;
	if(!pThread){ ASSERT(FALSE && _T("Cant get CurrentWinApp"));return;}

	CWnd* pWnd = pThread->GetMainWnd();
	if(!pWnd){ ASSERT(FALSE && _T("Cant get MainWnd"));return;}

	HWND hWnd = pWnd->m_hWnd;
	if(!hWnd){ ASSERT(FALSE && _T("Cant get the hadle of the MainWnd"));return;}

	::PostMessage(hWnd, WM_QUIT,0,0);
}


//events
COleVariant CStrawberrySvr::Fire_RaiseTheEvent(const COleVariant& Val1,const COleVariant& Val2,const COleVariant& Val3)
{
	HRESULT hr = S_OK;
	CComVariant varResult;
	int cConnections = m_vec.GetSize();

	for (int iConnection = 0; iConnection < cConnections; iConnection++)
	{
		this->Lock();
		CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);
		this->Unlock();

		IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);

		if (pConnection)
		{
			CComVariant avarParams[3];
			avarParams[0] = Val1;
			avarParams[1] = Val2;
			avarParams[2] = Val3;

			varResult.Clear();
			DISPPARAMS params = { avarParams, NULL, 3, 0 };
			hr = pConnection->Invoke(1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, &varResult, NULL, NULL);
		}
	}
	return varResult;
}

//methods
STDMETHODIMP CStrawberrySvr::get_program(BSTR* pVal)
{
	AFX_MANAGE_STATE(AfxGetAppModuleState());
	if(!pVal) return E_POINTER;

	*pVal = m_pOutputDoc->m_program.AllocSysString();;
	return S_OK;
}

STDMETHODIMP CStrawberrySvr::put_program(BSTR newVal)
{
	AFX_MANAGE_STATE(AfxGetAppModuleState());

	m_pOutputDoc->m_program = newVal;
	return S_OK;
}

STDMETHODIMP CStrawberrySvr::get_predicate(BSTR* pVal)
{
	AFX_MANAGE_STATE(AfxGetAppModuleState());
	if(!pVal) return E_POINTER;

	*pVal = m_pOutputDoc->m_predicate.AllocSysString();;
	return S_OK;
}

STDMETHODIMP CStrawberrySvr::put_predicate(BSTR newVal)
{
	AFX_MANAGE_STATE(AfxGetAppModuleState());

	m_pOutputDoc->m_predicate = newVal;
	return S_OK;
}

STDMETHODIMP CStrawberrySvr::get_arguments(BSTR* pVal)
{
	AFX_MANAGE_STATE(AfxGetAppModuleState());
	if(!pVal) return E_POINTER;

	*pVal = m_pOutputDoc->m_arguments.AllocSysString();
	return S_OK;
}

STDMETHODIMP CStrawberrySvr::put_arguments(BSTR newVal)
{
	AFX_MANAGE_STATE(AfxGetAppModuleState());

	m_pOutputDoc->m_arguments = newVal;
	return S_OK;
}

STDMETHODIMP CStrawberrySvr::get_result(VARIANT* pVal)
{
	AFX_MANAGE_STATE(AfxGetAppModuleState());
	if(!pVal) return E_POINTER;

	VariantClear(pVal);
  if (error==0)
	  *pVal = m_pOutputDoc->m_result;
	return S_OK;
}

STDMETHODIMP CStrawberrySvr::put_result(VARIANT newVal)
{
	AFX_MANAGE_STATE(AfxGetAppModuleState());
	
	VariantClear(&m_pOutputDoc->m_result);
  m_pOutputDoc->m_result = newVal;
	return S_OK;
}

STDMETHODIMP CStrawberrySvr::compile(LONG* plResult)
{
	AFX_MANAGE_STATE(AfxGetAppModuleState());
	if(!plResult) return E_POINTER;
	*plResult = 0;

	try{
		*plResult = m_pOutputDoc->compile_method();
	}catch(...){return E_FAIL;}

	return S_OK;
}

STDMETHODIMP CStrawberrySvr::call(LONG* plResult)
{
	AFX_MANAGE_STATE(AfxGetAppModuleState());
	if(!plResult) return E_POINTER;
	*plResult = 0;

	try{
		*plResult = m_pOutputDoc->call_method();
	}catch(...){return E_FAIL;}

	return S_OK;
}
