#pragma once


#include "stdafx.h"
#include "BlockItem_Real.h"

IMPLEMENT_SERIAL(CBlockItem_Real, CBlockItem, 1);

CBlockItem_Real::CBlockItem_Real()
{
	m_hModule = NULL;
	m_pBlock = NULL;
	m_pBlockAutoTrigger = NULL;
	m_pBlockConfig = NULL;
	m_strInputPortNameArray = NULL;
	m_strOutputPortNameArray = NULL;
	m_bInited = FALSE;
}

CBlockItem_Real::~CBlockItem_Real()
{
	ReleaseInterface();
	if ( m_strInputPortNameArray )
		delete[] m_strInputPortNameArray;
	if ( m_strOutputPortNameArray )
		delete[] m_strOutputPortNameArray;
}

CBlockItem_Real* CBlockItem_Real::CreateInstance()
{
	return new CBlockItem_Real();
}

BOOL CBlockItem_Real::InitInstance()
{
	if ( m_pBlock )
	{
		m_bInited = TRUE;
		return (S_OK == m_pBlock->InitInstance());
	}
	return TRUE;
}

BOOL CBlockItem_Real::ExitInstance()
{
	if ( m_pBlock && m_bInited )
		return (S_OK == m_pBlock->ExitInstance());
	return TRUE;
}

CString CBlockItem_Real::GetName() const
{
	return m_strBlockName;
}

CString CBlockItem_Real::GetDescription() const
{
	return m_strDescription;
}

CString CBlockItem_Real::GetInputPortName(DWORD dwPort) const
{
	ASSERT(dwPort < GetInputCount());
	return m_strInputPortNameArray[dwPort];
}

CString CBlockItem_Real::GetOutputPortName(DWORD dwPort) const
{
	ASSERT(dwPort < GetOutputCount());
	return m_strOutputPortNameArray[dwPort];
}

CString CBlockItem_Real::GetStatus() const
{
	CString ret;
	ret.Format(L"Last time: %.3fms", GetLastProcessingTime());
	return ret;
}

BOOL CBlockItem_Real::SetInputCount(const DWORD dwPorts)
{
	if ( m_strInputPortNameArray )
		delete[] m_strInputPortNameArray;
	CBlockItem::SetInputCount(dwPorts);
	m_strInputPortNameArray = new CString[dwPorts];
	return TRUE;
}

BOOL CBlockItem_Real::SetOutputCount(const DWORD dwPorts)
{
	if ( m_strOutputPortNameArray )
		delete[] m_strOutputPortNameArray;
	CBlockItem::SetOutputCount(dwPorts);
	m_strOutputPortNameArray = new CString[dwPorts];
	return TRUE;
}

const PORTDATA CBlockItem_Real::GetOutputPortData(DWORD dwPort) const
{
	if ( m_pBlock )
	{
		return m_pBlock->GetOutputPortData(dwPort);
	}

	PORTDATA ret;
	ZeroMemory(&ret, sizeof(ret));
	return ret;
}

LPCRITICAL_SECTION CBlockItem_Real::GetOutputCriticalSectionPtr(DWORD dwPort) const
{
	LPCRITICAL_SECTION ret = NULL;
	LPBLOCKDATA pData = NULL;
		ret = m_pBlock->GetCriticalSectionPtr();// pData->pCriticalSectionArray[dwPort];
	return ret;
}

BOOL CBlockItem_Real::GetModifiedFlag()
{
	return m_pBlock->GetModifiedFlag();
}

VOID CBlockItem_Real::SetModifiedFlag(BOOL bModified)
{
	m_pBlock->SetModifiedFlag(bModified);
}

BOOL CBlockItem_Real::ProcessData(const LPBLOCKDATA pInputData)
{
	ASSERT(m_pBlock);
	HRESULT hr;
	hr = m_pBlock->ProcessData(pInputData);
	return (S_OK == hr) ? TRUE : FALSE;
}

BOOL CBlockItem_Real::ClearRevMap(REVDATAMAP &rRevDataMapClean)
{
	ASSERT(m_pBlock);
	HRESULT hr;
	hr = m_pBlock->ClearRevMap(rRevDataMapClean);
	return (S_OK == hr) ? TRUE : FALSE;
}

BOOL CBlockItem_Real::ProcessRev(const DWORD dwProcessId, REVDATAMAP &rRevDataMap)
{
	ASSERT(m_pBlock);
	HRESULT hr;
	hr = m_pBlock->ProcessRev(dwProcessId, rRevDataMap);
	return (S_OK == hr) ? TRUE : FALSE;
}

BOOL CBlockItem_Real::Start()
{
	m_hAutoTrig.pDoc = m_pDocument;
	m_hAutoTrig.pItem = this;
	return m_pBlockAutoTrigger ? (m_pBlockAutoTrigger->Start((TRIGGERPROC)m_pDocument->TriggerProc, (HANDLE)&m_hAutoTrig) == S_OK) : FALSE;
}

BOOL CBlockItem_Real::Stop()
{
	return m_pBlockAutoTrigger ? (m_pBlockAutoTrigger->Stop() == S_OK) : FALSE;
}

void CBlockItem_Real::Serialize(CArchive &ar)
{
	CBlockItem::Serialize(ar);
	if ( ar.IsStoring() )
	{
		BYTE b = 0x00;
		if ( m_hModule )
			b = 0x01;
		ar << b;
		if ( 0x01 == b )
			ar << m_strLibName;
	}
	else
	{
		BYTE b;
		ar >> b;
		if ( 0x01 == b )
		{
			//ar >> m_strLibName;
			CString LibName;
			ar >> LibName;
			LoadInterface(LibName);
		}
	}
	if ( m_pBlock )
		m_pBlock->Serialize(ar);
}

BOOL CBlockItem_Real::ShowProperties(BOOL bTest)
{
	if ( bTest )
	{
		return (m_pBlockConfig) ? TRUE : FALSE;
	}
	return (m_pBlockConfig->ShowConfig() == S_OK) ? TRUE : FALSE;
}

CString CBlockItem_Real::GetBlockPath()
{
	CString ret;
	ASSERT(m_pBlock);
	m_pBlock->GetBlockPath(ret);
	return ret;
}

BOOL CBlockItem_Real::LoadInterface(LPCWSTR lpcLibName)
{
	if ( m_hModule )
		return FALSE;
	m_hModule = LoadLibrary(lpcLibName);
	m_strLibName = lpcLibName;
	if ( m_pBlock || m_pBlockAutoTrigger || m_pBlockConfig )
		return FALSE;
	CREATEPROC create = (CREATEPROC)GetProcAddress(m_hModule, "CreateBlockInstance");
	if ( create )
	{
		if ( SUCCEEDED(create(IID_IBlock, (void**)&m_pBlock)) )
		{
			DWORD dwPorts;
			if ( SUCCEEDED(m_pBlock->GetInputCount(&dwPorts)) )
			{
				SetInputCount(dwPorts);
				for ( DWORD i = 0; i < dwPorts; i++ )
				{
					m_pBlock->GetInputPortName(i, m_strInputPortNameArray[i]); 
				}
			}
			if ( SUCCEEDED(m_pBlock->GetOutputCount(&dwPorts)) )
			{
				SetOutputCount(dwPorts);
				for ( DWORD i = 0; i < dwPorts; i++ )
				{
					m_pBlock->GetOutputPortName(i, m_strOutputPortNameArray[i]); 
				}
			}
			m_pBlock->GetName(m_strBlockName);
			m_pBlock->GetDescription(m_strDescription);

			// pokusime se pridat konfiguracni interface
			m_pBlock->QueryInterface(IID_IBlockConfig, (void**)&m_pBlockConfig);
			// pokusime se pridat rozhrani automatickeho spousteni
			m_pBlock->QueryInterface(IID_IBlockAutoTrigger, (void**)&m_pBlockAutoTrigger);
		}
		else
		{
			return FALSE;
		}
	}
	else
	{
		return FALSE;
	}
	return TRUE;
}

BOOL CBlockItem_Real::ReleaseInterface()
{
	if ( !m_hModule )
		return FALSE;
	if ( m_pBlock )
		m_pBlock->Release();
	if ( m_pBlockAutoTrigger )
		m_pBlockAutoTrigger->Release();
	if ( m_pBlockConfig )
		m_pBlockConfig->Release();
	m_pBlock = NULL;
	m_pBlockAutoTrigger = NULL;
	m_pBlockConfig = NULL;
	m_hModule = NULL;
	m_strLibName = L"";
	return TRUE;
}