#include "stdafx.h"
#include "BlockItem_Output.h"
#include "BlockItem_OutputProps.h"
#include "BlockItem_Virtual.h"
#include "SchemeDoc.h"

IMPLEMENT_SERIAL(CBlockItem_Output, CBlockItem, 1);

CBlockItem_Output::CBlockItem_Output()
{
	m_strName = "Output block";
	m_strDesc = "Can be assigned to Output of parent virtual block";
	ZeroMemory(&m_blockData, sizeof(m_blockData));
	SetInputCount(1);
	m_pWndProps = new CBlockItem_OutputProps(NULL, this);
	m_dwTargetPort = -1;

	m_blockData.dwDataLenArrayArray = new DWORD*[1];
	m_blockData.dwLayersArray = new DWORD[1];
//	m_blockData.pCriticalSectionArray = new CRITICAL_SECTION*[1];
	m_blockData.pDataArrayArray = new void**[1];
}

CBlockItem_Output::~CBlockItem_Output()
{
	delete[] (m_blockData.dwDataLenArrayArray);
	delete[] (m_blockData.dwLayersArray);
//	delete[] (m_blockData.pCriticalSectionArray);
	delete[] (m_blockData.pDataArrayArray);
	delete(m_pWndProps);
}

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

void CBlockItem_Output::Serialize(CArchive &ar)
{
	CBlockItem::Serialize(ar);
	if ( ar.IsStoring() )
	{
		ar << m_dwTargetPort;
		ar << m_strName;
	}
	else
	{
		DWORD dwPort;
		ar >> dwPort;
		if ( dwPort != -1 )
			Assign(dwPort);
		else
			UnAssign();
		ar >> m_strName;
	}
}

CString CBlockItem_Output::GetName() const
{
	return m_strName;
}

CString CBlockItem_Output::GetDescription() const
{
	return m_strDesc;
}

CString CBlockItem_Output::GetStatus() const
{
	CString ret;
	if ( m_dwTargetPort != -1 )
	{
		ret.Format(L"Assigned to port %d", m_dwTargetPort);
	}
	else
		ret.Format(L"Unassigned");
	return ret;
}

CString CBlockItem_Output::GetInputPortName(DWORD dwPort) const
{
	return L"";
}

BOOL CBlockItem_Output::SetName(const CString strName)
{
	m_strName = strName;
	return TRUE;
}

BOOL CBlockItem_Output::SetDescription(const CString strDesc)
{
	m_strDesc = strDesc;
	return TRUE;
}

BOOL CBlockItem_Output::InitInstance()
{
	return TRUE;
}

BOOL CBlockItem_Output::ExitInstance()
{
	return TRUE;
}

BOOL CBlockItem_Output::Run()
{
	return TRUE;
}

BOOL CBlockItem_Output::Stop()
{
	return TRUE;
}

BOOL CBlockItem_Output::ShowProperties(BOOL bTest)
{
	if ( bTest )
		return TRUE;
	if ( !m_pWndProps->m_hWnd )
	{
		m_pWndProps->Create(IDD_PORTPROPS);
	}
	else
	{
		m_pWndProps->SetForegroundWindow();
		m_pWndProps->ShowWindow(SW_SHOW);
	}
	return TRUE;
}

BOOL CBlockItem_Output::Assign(DWORD dwPort)
{
	CBlockItem_Virtual* pParent;
	if ( pParent = GetParentBlock() )
	{
		ASSERT(dwPort < pParent->GetOutputCount());
		if ( -1 != m_dwTargetPort )
			pParent->SetOutputBlock(m_dwTargetPort, NULL);
		pParent->SetOutputBlock(dwPort, this);
		m_dwTargetPort = dwPort;
	}
	return TRUE;
}

BOOL CBlockItem_Output::UnAssign()
{
	m_dwTargetPort = -1; // zajistit prekresleni dialogu
	return TRUE;
}

BOOL CBlockItem_Output::GetAssignment(LPDWORD pdw) const
{
	if ( m_dwTargetPort != -1 )
	{
		*pdw = m_dwTargetPort;
		return TRUE;
	}
	return FALSE;
}

BOOL CBlockItem_Output::UpdatePortList()
{
	if ( m_pWndProps->m_hWnd )
		return m_pWndProps->UpdatePortList();
	else return FALSE;
}

const PORTDATA CBlockItem_Output::GetOutputPortData(DWORD dwPort)
{
	ASSERT(dwPort == 0); // blok ma vzdy pouze jeden port
	
	CBlockItem *pTgtBlock;
	DWORD dwTgtPort;
	if ( GetInConnectorTarget(dwPort, &pTgtBlock, &dwTgtPort) )
	{
		return pTgtBlock->GetOutputPortData(dwTgtPort);
	}

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

LPCRITICAL_SECTION CBlockItem_Output::GetOutputCriticalSectionPtr(DWORD dwPort)
{
	ASSERT(dwPort == 0);	// tento blok ma vzdy pouze jeden port
	CBlockItem* pTgtBlock;
	DWORD dwTgtPort;
	if ( GetInConnectorTarget(dwPort, &pTgtBlock, &dwTgtPort) )
		return ( pTgtBlock->GetOutputCriticalSectionPtr(dwTgtPort) );
	return NULL;
}

BOOL CBlockItem_Output::Process(DWORD dwProcessId, REVDATAMAP &rRevDataMap)
{
	CBlockItem* pTgtBlock;
	DWORD dwTgtPort;
	if ( GetInConnectorTarget(0, &pTgtBlock, &dwTgtPort) && pTgtBlock )
	{
		pTgtBlock->Process(dwProcessId, rRevDataMap);
	}
	//m_pDocument->UpdateViewer_Safe(this);
	return TRUE;
}