// ModuleString.cpp: implementation of the CModuleString class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "addin.h"
#include "ModuleString.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
// spock
//#import "C:\\Program Files\\1Cv77\\BIN\\zlibeng.dll" no_namespace
#include "zlibeng.tlh"
// spock

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//CBLModule7

bool CModuleString::LoadModuleFromERT(const CString& strFileName)
{
  IStoragePtr pStgRoot;
  IStorage* pStorage = NULL;
  HRESULT hr;
  USES_CONVERSION;
  hr = ::StgOpenStorage(
          T2COLE(strFileName),
          NULL,
          STGM_READ | STGM_SHARE_DENY_WRITE,
          //STGM_READ,
          NULL,
          0,
          &pStorage);

  if (FAILED(hr))
  {	//ошибка
    CString StrError;
    StrError = "Не удалось прочитать файл: ";
    StrError += strFileName;
    pBkEndUI->DoMessageLine(StrError, mmBlackErr);	
    return false;
  }              
  pStgRoot.Attach(pStorage, false);

  IStreamPtr pStream;
  IStream *pIStr = NULL;
  hr = pStgRoot->OpenStream(T2COLE("MD Programm text"),0,STGM_READ | STGM_SHARE_EXCLUSIVE,0,&pIStr);
  if( FAILED(hr) ) 
  {
    pBkEndUI->DoMessageLine("failed IStorage::OpenStream", mmBlackErr);	            
    return false;        
  }
  pStream.Attach(pIStr, false);    

  IStreamPtr pStreamOut;
  pIStr = NULL;
  if (S_OK != CreateStreamOnHGlobal(NULL, TRUE, &pIStr))
  {
    pBkEndUI->DoMessageLine("error in CreateStreamOnHGlobal", mmBlackErr);    
    return false; 
  }

  pStreamOut.Attach(pIStr, false);
  try 
  {
    IzlibEnginePtr iLibEngine;
    iLibEngine.CreateInstance(L"V75.zlibEngine");

    hr = iLibEngine->pkDecompress(pStream, pStreamOut);            

    if (FAILED(hr))
    {
      pBkEndUI->DoMessageLine("error iLibEngine->pkDecompress", mmBlackErr);          
      return false;
    }          

    STATSTG St;
    pStreamOut->Stat(&St, STATFLAG_NONAME);
    ULONG cbStreamSizeOut = St.cbSize.LowPart;                               
    LPTSTR lpStr = GetBufferSetLength(cbStreamSizeOut);
    if (lpStr == NULL)
    {
      pBkEndUI->DoMessageLine("lpStr == NULL", mmBlackErr);	                            
      return false;
	}

    LARGE_INTEGER __zero;
    __zero.QuadPart = __int64(0);
    if (pStreamOut->Seek(__zero, 0, NULL) != S_OK)
    {
      pBkEndUI->DoMessageLine("pStreamOut->Seek(__zero, 0, NULL) != S_OK", mmBlackErr);	                            
      return false;
    }

    ULONG pcbRead = 0;

    // main job here
	if (pStreamOut->Read(&lpStr[0], cbStreamSizeOut, &pcbRead) != S_OK)
    
	{
      pBkEndUI->DoMessageLine("pStreamOut->Read(&lpStr[0], cbStreamSizeOut, &pcbRead) != S_OK", mmBlackErr);	                            
      return false;
    }              

  } 
  catch (_com_error& err) 
  {
    CString str;
    str.Format("V75.zlibEngine Error:%s", err.ErrorMessage());
    pBkEndUI->DoMessageLine(str, mmBlackErr);
    return false;
  }                  

  return true;    
}

bool CModuleString::LoadModuleFromMD(const CString& strFileName)
{
	int npos = strFileName.Find("@MD");
    if (-1 == npos)
		npos = strFileName.Find("@md");

	CString nameRep = strFileName.Left(npos);
	CMetaDataCont *pMD = GetMetaData();

	CMetaDataObj* pObj=(CMetaDataObj*)pMD->GetCalcVarDef(nameRep);
	if (pObj)
	{
		long id=pObj->GetID();
		CTypedCont* pCont=NULL;
		CString text;
		CConfigCont::IDToPath(id,"CalcVar",text,&pCont,FALSE);

		if(pCont)
		{
			CTxtModuleReader* pText = (CTxtModuleReader*)pCont->GetTextDocument();
			
			// main job here
			pText->GetText(*this);
		}
		return true;
	}
	else
	{
		return false;
	}
}

bool CModuleString::LoadModuleFromFile(const CString& strFileName)
{
	CFile ComponentFile;
	if (ComponentFile.Open(strFileName, CFile::modeRead))
	{  
		DWORD dwLength = ComponentFile.GetLength();

		// main job here
		LPTSTR buff = GetBuffer(dwLength);
		ComponentFile.Read(buff, dwLength);

		ReleaseBuffer(dwLength);
		ComponentFile.Close();
		return true;
	}
	else
	{
		CString StrError;
		StrError = "Не удалось прочитать файл: ";
		StrError += strFileName;
		pBkEndUI->DoMessageLine(StrError, mmBlackErr);	
		return false;
	}
}

// АЛьФ --->
typedef LPCSTR (WINAPI *PF_GetClassText)(LPCSTR lpStr);

bool CModuleString::LoadModuleFromDLL(const CString& strFileName)
{
	int npos = strFileName.Find("@");
    if (-1 == npos)
	{
		pBkEndUI->DoMessageLine("Неверный формат описания имени класса в dll.", mmBlackErr);	
		return false; // неверный формат имени класса в dll
	}

	CString nameClass = strFileName.Left(npos);
	CString nameFile = AbsoluteFilePath(AllTrim(strFileName.Mid(npos+1)));
	HMODULE hDll = ::LoadLibrary(LPCSTR(nameFile));
	if(hDll == NULL)
	{
		CString StrError;
		StrError = "Ошибка при загрузке файла: ";
		StrError += nameFile;
		pBkEndUI->DoMessageLine(StrError, mmBlackErr);	
		return false;
	}
	PF_GetClassText hGetClassText = (PF_GetClassText)::GetProcAddress(hDll, "GetClassText");
	if(hGetClassText == NULL)
	{
		CString StrError;
		StrError = "Не найдена функция GetClassText() в библиотеке: ";
		StrError += nameFile;
		pBkEndUI->DoMessageLine(StrError, mmBlackErr);
		::FreeLibrary(hDll);
		return false;
	}
	(*this) = (*hGetClassText)(nameClass);
	::FreeLibrary(hDll);

	return true;
}
// АЛьФ <---

bool CModuleString::LoadModule(const CString& strFileName)
{
	// АЛьФ - старый код, на всякий случай, оставлю в комментарии
	// неплохо все же сделать тут полную регистронезависимость - приводить строку
	// к верхнему регистру
	// начал было это делать, но сравнение на "@MD" и "@md" встречается и в других
	// местах исходников, поэтому оставляю как есть
	if (strFileName.Find(".ert") != -1)
	{
		return LoadModuleFromERT(strFileName);
	}
	else
	{
		if ((strFileName.Find("@MD") != -1) || (strFileName.Find("@md") != -1))
		{
			return LoadModuleFromMD(strFileName);
		}
		else
		{
			if (strFileName.Find(".dll") != -1)
			{
				return LoadModuleFromDLL(strFileName);
			}
			else
			{
				return LoadModuleFromFile(strFileName);
			}
		}
	}
	/*
  if (strFileName.Find(".ert") != -1)
  {
	  return LoadModuleFromERT(strFileName);
  }
  else
  {
    if (strFileName.Find("@MD") != -1)
    {
		return LoadModuleFromMD(strFileName);
    }
    else
	if (strFileName.Find("@md") != -1)
    {
		return LoadModuleFromMD(strFileName);
    }
	else
    {
			return LoadModuleFromFile(strFileName);
    }
  }
	*/

}

void CModuleString::CropModuleToClass(const CString& strClassName)
{
	int posBegin = 0;
	int posEnd = GetLength();

	int findBegin = Find("//# ClassBegin "+ strClassName+";");
	int findEnd = Find("//# ClassEnd " + strClassName+";");

	if (findBegin != -1)
		posBegin = findBegin;
	if (findEnd != -1)
		posEnd = findEnd;

	Delete(posEnd, GetLength() - posEnd);
	Delete(0, posBegin);
}

bool CModuleString::LoadModule(const CString& strFileName, const CString& strClassName)
{
	if (LoadModule(strFileName))
	{
		CropModuleToClass(strClassName);
		return true;
	}

	return false;
}
