// ComponentClass.h: interface for the CComponentClass class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_COMPONENTCLASS_H__5F1978A2_67C1_4AAB_8C12_44790D3700B2__INCLUDED_)
#define AFX_COMPONENTCLASS_H__5F1978A2_67C1_4AAB_8C12_44790D3700B2__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "MapDefMethod.h"
//#include "CodeDecodeFile.h"
#include "paramdefs.h"
#include "ModuleString.h"
#include "SetOfHierarchy.h"

//kms
#include "SafeContext.h"

extern CBkEndUI * pBkEndUI;

// пока закомментарил
//typedef class CArray<CBLModule7*,CBLModule7*> CBLModuleArray;
/*
// простой класс-указатель
template <class Type>
class TPtr{
  Type* p;
public:
  TPtr(Type* src){p=src;}
  Type* operator ->(){return p;}
  operator Type*(){return p;}
};

// умный класс-указатель
// автоматически создает объекты через new
// а в деструкторе удаляет
// удобно использовать для стековых локальных объектов
//
template <class Type>
class TMP{
  Type* p;
public:
  TMP(){
  p=new Type();
  }
  TMP(const Type& value)
  { p=new Type(value); }
  ~TMP(){
  delete p;
  }
  Type* operator ->(){if (!p) puts("NULL обращение"); return p;}
  operator Type*(){if (!p) puts("NULL обращение"); return p;}
};
*/

//public CStdOleBLContext  
class CComponentClass : public CBLContext
{
DECLARE_DYNCREATE(CComponentClass);
public:
	static void SetDebugInfo(CComponentClass *pComp);
	static void ClearDebugInfo();
	static bool isExceptionStatus;
	static CString strTextException;
	static CValue* ExceptionValue;

	static void GetFullTypeName(CBLContext *pCont, CString& rus, CString& eng, bool bAddKind = true);
	static void GetFullTypeName(CBLContext *pCont, CString& rus, CString& eng, 
		CString& rusKind, bool bAddKind = true); // artbear

	inline int ReplaceInstBaseClasses(const CValue &NameClass, const CValue &Instance, CValue &rValue);

	inline int IsObject(const CValue &NameClass, CValue &rValue) const;

	inline int GetBaseClass(const CValue &NameClass, CValue & rValue) const;
	BOOL GetBaseClass(const CRuntimeClass* pRTClass, CBLContext** ppBaseObj) const;
    template <class T>
    BOOL GetBaseClass(T** ppT) const
    {
        for (CONST_ITER_CONT iter = vecOfBaseCont.begin(); iter != vecOfBaseCont.end(); ++iter)
        {
			CBLContext *pCont = *iter;
            if ((pCont)->GetRuntimeClass() == RUNTIME_CLASS(CComponentClass))
            {
				// artbear
                //if (static_cast<CComponentClass*>(*iter)->GetBaseClass(ppT))
//				PCBLContext pCont = *iter;
                if (static_cast<CComponentClass*>(pCont)->GetBaseClass(ppT))
                    return TRUE;
            }
            else
            {
				// artbear
                //T* p = dynamic_cast<T*>(*iter);
//				PCBLContext pCont = **iter;
                T* p = dynamic_cast<T*>(pCont);
                if (p)
                {
                    *ppT = p;
                    return TRUE;
                }
            }
        }
        return FALSE;
    };
	CBLModule * GetModule() const;
	CBLModule * GetHostModule() const;
	void InvokeConstructor();

	//virtual CBLModuleWrapper* Init(const char* file, CComponentClass* pCreatedCompModule);
	virtual CBLModule* Init(const char* file, CComponentClass* pCreatedCompModule);
	void OpenDebugForm();

	void ShowError(const char *);
	CComponentClass();
	virtual ~CComponentClass();
 
  enum {
  fuctGetBaseClass,
  //procRegObj,
  //procUnRegObj,
  procAssignFriendModule,

  // этот функционал закрыт общее решение artbear 
  // TODO возможно, в дальнейшем он должен быть открыт внутри класса, а снаружи невидим
  //
  //procAddBaseClass,

  funcSendMessageOwnMod,
  funcGetPathName,
  //procBegPostNestedDoc,
  //procEndPostNestedDoc,
  funcGetEnvContext,
  funcGetParamsList,

  funcReplaceInstBaseClasses,
  funcReplaceInstBaseClasses_SYN1,

  funcSetOnIndexParams,
  procOnOpen,
  procThrow,
  funcIsObject,
	lastMethod
	};

  static class CMapDefMethod MapDef;
  
  virtual int  CallAsFunc(int,class CValue &,class CValue * *);	//935
	virtual int  CallAsProc(int,class CValue * *);	//937
	virtual void  DecrRef(void);	//1086
	virtual int  FindMethod(char const *)const;	//1366
	virtual int  FindProp(char const *)const;	//1369
	virtual char const *  GetCode(void)const;	//1544
	virtual int  GetDestroyUnRefd(void)const;	//1657
	virtual void  GetExactValue(class CValue &);	//1708
	virtual class CObjID   GetID(void)const;	//1804
	virtual class CBLContextInternalData *  GetInternalData(void);	//1826
	virtual char const *  GetMethodName(int,int)const;	//1964
	virtual int  GetNMethods(void)const;	//2005
	virtual int  GetNParams(int)const;	//2008
	virtual int  GetNProps(void)const;	//2015
	virtual int  GetParamDefValue(int,int,class CValue *)const;	//2122
	virtual char const *  GetPropName(int,int)const;	//2187
	virtual int  GetPropVal(int,class CValue &)const;	//2221
	virtual long  GetTypeID(void)const;	//2505
	virtual char const *  GetTypeString(void)const;	//2513
	virtual class CType   GetValueType(void)const;	//2547
	virtual int  HasRetVal(int)const;	//2657
	virtual void  IncrRef(void);	//2668
	virtual void  InitObject(class CType const &);	//2721
	virtual void  InitObject(char const *);	//2722
	virtual int  IsExactValue(void)const;	//2808
	virtual int  IsOleContext(void)const;	//2846
	virtual int  IsPropReadable(int)const;	//2863
	virtual int  IsPropWritable(int)const;	//2865
	virtual int  IsSerializable(void);	//2874
	virtual int  SaveToString(class CString &);	//3295
	virtual void  SelectByID(class CObjID,long);	//3350
	virtual int  SetPropVal(int,class CValue const &);	//3694
  void SetNestedObj(CBLContext* pCont);
	static class CObjID ObjID;
  
  mutable CMapStringToPtr   m_BindInstaceValueList;
  static void ThrowException(bool isThrow = true);

  // найти метод класса по названию
  // сначала ищется в модуле класса на случай, если задан без Экспорт
  // а затем в экспортируемых методах класса, затем в наследниках 
  //
  // сначала ищется русское имя, а затем английское
  //
  static int FindMethod(CBLContext* pContext, CBLModule *pMod, LPCTSTR sNameRus, LPCTSTR sNameEng);
  
  // тоже самое, но для текущего класса
  inline int FindMethod(CBLModule *pMod, LPCTSTR sNameRus, LPCTSTR sNameEng) const
  {
	return CComponentClass::FindMethod((CBLContext*)this, pMod, sNameRus, sNameEng);
  };

protected:
  
  //CBLModuleWrapper *m_pModule;
  CBLModule  *m_pModule;
  CBLModule  *m_pHostModule;
  CBLContext *m_pDebugContext;
private:		
  friend class CSetOfHierarchy;

	CString m_NameOfInstance;
/*
  list<CBLContext *> vecOfBaseCont;
  typedef list<CBLContext *>::const_iterator CONST_ITER_CONT;
  typedef list<CBLContext *>::iterator ITER_CONT;    
*/

// artbear
  list<CSafeContext> vecOfBaseCont;
  typedef list<CSafeContext>::const_iterator CONST_ITER_CONT;
  typedef list<CSafeContext>::iterator ITER_CONT;

  class CParamDefs *defFnNames;
  struct MethParamsDef 
  {
    int nNumberOfMeth;
    int nRealNumberOfMeth;
    CBLContext* pContext;
  }; 
  mutable MethParamsDef m_MethParamsDef;  
  
  inline int CallAsMethod(int iMethNum, CValue * *ppValue, bool bHasRetVal = false, CValue * pRetValue = NULL);
  
  static CComponentClass* m_CurDebugObject;
  bool m_isCreateOptimizeMode;
};

#endif // !defined(AFX_COMPONENTCLASS_H__5F1978A2_67C1_4AAB_8C12_44790D3700B2__INCLUDED_)
