#include "stdafx.h"
#include "BlockItem_Input.h"
#include "BlockItem_InputProps.h"
#include "BlockItem_Virtual.h"
#include "SchemeDoc.h"

IMPLEMENT_SERIAL(CBlockItem_Input, CBlockItem, 1);

CBlockItem_Input::CBlockItem_Input()
{
	m_strName = "Input block";
	m_strDesc = "Can be assigned to input of parent virtual block";
	SetOutputCount(1);
	ZeroMemory(&m_blockData, sizeof(m_blockData));
	m_pWndProps = new CBlockItem_InputProps(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_Input::~CBlockItem_Input()
{
	delete[] (m_blockData.dwDataLenArrayArray);
	delete[] (m_blockData.dwLayersArray);
//	delete[] (m_blockData.pCriticalSectionArray);
	delete[] (m_blockData.pDataArrayArray);
	delete(m_pWndProps);
}

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

void CBlockItem_Input::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_Input::GetName() const
{
	return m_strName;
}

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

CString CBlockItem_Input::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_Input::GetOutputPortName(DWORD dwPort) const
{
	return L"";
}

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

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

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

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

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

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

BOOL CBlockItem_Input::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_Input::Assign(DWORD dwPort)
{
	CBlockItem_Virtual* pParent;
	if ( pParent = GetParentBlock() )
	{
		ASSERT(dwPort < pParent->GetInputCount());
		if ( -1 != m_dwTargetPort )
			pParent->SetInputBlock(m_dwTargetPort, NULL);
		GetParentBlock()->SetInputBlock(dwPort, this);
		m_dwTargetPort = dwPort;
	}
	return TRUE;
}

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

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

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

const PORTDATA CBlockItem_Input::GetOutputPortData(DWORD dwPort) const
{
	DWORD dwParentPort;
	CBlockItem* pTgtBlock;
	DWORD dwTgtPort;
	CBlockItem *pParentBlock = GetParentBlock();
	if ( pParentBlock && GetAssignment(&dwParentPort) && 
		pParentBlock->GetInConnectorTarget(dwParentPort, &pTgtBlock, &dwTgtPort) )
	{
		return pTgtBlock->GetOutputPortData(dwTgtPort);
	}

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

LPCRITICAL_SECTION CBlockItem_Input::GetOutputCriticalSectionPtr(DWORD dwPort) const
{
	CBlockItem* pParentBlock = GetParentBlock();
	CBlockItem* pTgtBlock;
	DWORD dwTgtPort;
	DWORD dwParentPort;
	if ( GetAssignment(&dwParentPort) )
	{
		if ( pParentBlock && pParentBlock->GetInConnectorTarget(dwParentPort, &pTgtBlock, &dwTgtPort) )
		{
			return pTgtBlock->GetOutputCriticalSectionPtr(dwTgtPort);
		}
	}
	return NULL;
}

BOOL CBlockItem_Input::Process(DWORD dwProcessId, REVDATAMAP &rRevDataMap)
{
	DWORD dwParentPort;
	if ( GetAssignment(&dwParentPort) && dwParentPort != -1 )
	{
		CBlockItem_Virtual *pParent;
		if ( pParent = GetParentBlock() )
		{
			CBlockItem *pTgtBlock;
			DWORD dwTgtPort;
			if ( pParent->GetInConnectorTarget(dwParentPort, &pTgtBlock, &dwTgtPort) )
			{
				pTgtBlock->Process(dwProcessId, rRevDataMap);
			}
		}
	}
	//m_pDocument->UpdateViewer_Safe(this);
	return TRUE;
}