// EventManager.cpp: implementation of the CEventManager class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "addin.h"
#include "EventManager.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////


extern CMetaDataCont * pMetaDataCont;
extern CBkEndUI * pBkEndUI;

IMPLEMENT_DYNCREATE(CEventManager, CBLContext);

class CObjID CEventManager::ObjID;


//////////////////////////////////////////////////////////////////////
// Описание методов и функций класса для 1С языка
// {{<"English_description">,<"Русское_название">},<0-это процедура, 1-это функция>,<Количество параметров>}
//////////////////////////////////////////////////////////////////////
struct CEventManager::paramdefs CEventManager::defFnNames[] = {
	{"IsEmpty","Пустой",1,0},
	{"AddEventHandle","ДобавитьОбработчикСобытия",1,2},
	{"RemEventHandle","УдалитьОбработчикСобытия",1,2},
	{"SendEvent","ПослатьСобытие",1,2},
	{"SetDelegate","УстановитьДелегата",1,1},
	{"Clear","Очистить",0,0},
	{"SetCountOfParams","УстановитьКоличествоПараметров",0,1},  
	{NULL,NULL,0,0}
};
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CEventManager::CEventManager()
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());	
	CBLContext *pCont = CBLContext::CreateInstance("Delegate");
	if (pCont)
	{
		pDelegate = static_cast<CDelegate *>(pCont);
//k		CValue par1(2L);
//k		CValue par2(1L);
//k		CValue *params[2] = {&par1, &par2};
//k		pDelegate->procDefineType(params);
		pDelegate->DefineType(2, 1, 1);
	}
	else
		CBLModule::RaiseExtRuntimeError("Невозможно создать агрегатный объект Delegate!" ,0);
	
}

CEventManager::~CEventManager()
{  
	pDelegate->DecrRef();  
}

int  CEventManager::CallAsFunc(int iMethNum,class CValue & rValue,class CValue * *ppValue)
{
	switch(iMethNum)
	{
    case funcIsEmpty:
		{
			//k      rValue =  CNumeric(pDelegate->IsEmpty() ? 1 : 0);
			//return 1;
			return pDelegate->funcIsEmpty(rValue, ppValue);
		}
		break;
    case funcAddEventHandle:
		{
			CString strNameMeth = ppValue[1]->GetString();
			if (strNameMeth.IsEmpty())      
				CBLModule::RaiseExtRuntimeError("Во второй параметр AddEventHandle необходимо передавать название метода!" ,0);
			
			CBLContext *pCont = ppValue[0]->GetContext();
			if (!pCont)
				CBLModule::RaiseExtRuntimeError("В первый параметр AddEventHandle необходимо передавать экземпляр класса 1C++ (воспользуйтесь: CreateObject())!" ,0);

			rValue = pDelegate->Add(ppValue, NULL);
			//k      if (pDelegate->AddMethodForDelegate(rValue, ppValue, false))
			return 1;
			//k      else
			//k        return -1;      
		}
		break;
    case funcRemEventHandle:
		{
			CString strNameMeth = ppValue[1]->GetString();
			if (strNameMeth.IsEmpty())      
				CBLModule::RaiseExtRuntimeError("Во второй параметр RemEventHandle необходимо передавать название метода!" ,0);
			
			CBLContext *pCont = ppValue[0]->GetContext();
			if (!pCont)
				CBLModule::RaiseExtRuntimeError("В первый параметр RemEventHandle необходимо передавать экземпляр класса 1C++ (воспользуйтесь: CreateObject())!" ,0);
			
			return (pDelegate->funcRemove(rValue, ppValue));
			//k      if (pDelegate->DeleteMethodsFromDelegate(rValue, ppValue))
			//k return 1;
			//k      else
			//k        return -1;      
		}
		break;
    case funcSendEvents:
		{
			pDelegate->Invoke(rValue, ppValue, true);
			//k      pDelegate->Invoke(rValue, ppValue, true);        
		}
		break;
    case funcSetDelegate:
		{        
			CBLContext *pCont = ppValue[0]->GetContext();
			bool bError = false;
			if (pCont)
			{
				CString strClassName(pCont->GetRuntimeClass()->m_lpszClassName);
				if (strClassName != "CDelegate")
					bError = true;
			}
			else
				bError = true;
			if (bError)
				CBLModule::RaiseExtRuntimeError("В SetDelegate(InstanceOfDelegate) к качестве параметра необходимо передавть экземпляр класса Делегат!" ,0);
			
			rValue.Reset();
			rValue.AssignContext(pDelegate);
			pDelegate->DecrRef();
			pDelegate = static_cast<CDelegate *>(pCont);
			pDelegate->IncrRef();
			
		}
		break;
	default:
		{           
		}
	};
	return -1;
}

int  CEventManager::CallAsProc(int iMethNum,class CValue * * ppValue)
{
	switch(iMethNum)
	{
    case procClear:
		{       
			//k      pDelegate->EraseDelegate(false);
			pDelegate->Erase(false);
			return 1;
		}
		break;
    case procSetCountOfParams:
		{
			pDelegate->DefineType(ppValue[0]->GetNumeric(), 1, 1);
			//k      pDelegate->EraseDelegate();      
			//k CValue par2(1L);
			//k CValue *params[2] = {ppValue[0], &par2};
			//k      pDelegate->SetTypeOfDelegate(params);
			return 1;
		}
	default:
		{           
			
		}
	};  
	return -1;
}

int  CEventManager::FindMethod(char const * lpMethodName)const
{
	int i;
	for (i = 0;i<lastMethod;i++){
		if (!stricmp(lpMethodName,defFnNames[i].Names[0]))
			return i;
		if (!stricmp(lpMethodName,defFnNames[i].Names[1]))
			return i;
	}
	return -1;
}

char const *  CEventManager::GetMethodName(int iMethodNum,int iMethodAlias)const
{
	if (iMethodNum >= lastMethod) 
		return "mError";
	else
		return defFnNames[iMethodNum].Names[iMethodAlias];
}

int  CEventManager::GetNMethods(void)const
{
	return lastMethod;
}

int  CEventManager::HasRetVal(int iMethodNum)const
{	
	return defFnNames[iMethodNum].HasReturnValue ;
}

int CEventManager::GetNParams(int iMethodNum)const
{	
	if (iMethodNum == funcSendEvents)
		return pDelegate->GetDefinedParamCount();
	else
		return defFnNames[iMethodNum].NumberOfParams;
}

int  CEventManager::GetParamDefValue(int iMethodNum,int iParamNum,class CValue * pDefValue)const
{	
	return 0;
}

void  CEventManager::DecrRef(void)
{
	CBLContext::DecrRef();
}

char const *  CEventManager::GetCode(void)const
{
	return 0;
}

int  CEventManager::GetDestroyUnRefd(void)const
{
	return 1;
}

void  CEventManager::GetExactValue(class CValue & vParam)
{
	CBLContext::GetExactValue(vParam);
}

class CObjID   CEventManager::GetID(void)const
{
	return ObjID;
}

class CBLContextInternalData *  CEventManager::GetInternalData(void)
{
	return CBLContext::GetInternalData();
}


long  CEventManager::GetTypeID(void)const
{
	return 100;
}

char const *  CEventManager::GetTypeString(void)const
{
	return "EventManager";
}

class CType   CEventManager::GetValueType(void)const
{
	CType tType(100);
	
	return tType;
}

void  CEventManager::IncrRef(void)
{
	CBLContext::IncrRef();
}

void  CEventManager::InitObject(class CType const & tType)
{
	CBLContext::InitObject(tType);
}

void  CEventManager::InitObject(char const * strName)
{
	CBLContext::InitObject(strName);
}

int  CEventManager::IsExactValue(void)const
{
	return 0;
}

int  CEventManager::IsOleContext(void)const
{
	return 0;
}

int  CEventManager::IsPropReadable(int iPropNum)const
{
	return 1;
}

int  CEventManager::IsPropWritable(int iPropNum)const
{
	return 1;
}

int  CEventManager::IsSerializable(void)
{
	return 0;
}

int  CEventManager::SaveToString(class CString & csStr)
{
	csStr = "DJK";
	return 1;
}

void  CEventManager::SelectByID(class CObjID cID,long lNum)
{
	CBLContext::SelectByID(cID,lNum);
}


int  CEventManager::GetNProps(void)const
{
	return 0;
}

char const *  CEventManager::GetPropName(int A,int B)const
{
	return NULL;
}

int  CEventManager::GetPropVal(int iPropNum,class CValue & rValue)const
{
	return -1;
}

int  CEventManager::SetPropVal(int iPropNum,class CValue const & vValue)
{
	return -1;
}

int  CEventManager::FindProp(char const * Name)const
{
	return -1;
}
