/*****************************************************************************
* Copyright (c) 1990-98 Digi International Inc., All Rights Reserved
* 
* This software contains proprietary and confidential information of Digi
* International Inc.  By accepting transfer of this copy, Recipient agrees
* to retain this software in confidence, to prevent disclosure to others,
* and to make no use of this software other than that for which it was
* delivered.  This is an unpublished copyrighted work of Digi International
* Inc.  Except as permitted by federal law, 17 USC 117, copying is strictly
* prohibited.
* 
* Restricted Rights Legend
*
* Use, duplication, or disclosure by the Government is subject to
* restrictions set forth in sub-paragraph (c)(1)(ii) of The Rights in
* Technical Data and Computer Software clause at DFARS 252.227-7031 or
* subparagraphs (c)(1) and (2) of the Commercial Computer Software -
* Restricted Rights at 48 CFR 52.227-19, as applicable.
*
* Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
*
*****************************************************************************/
// ServiceX25.cpp: implementation of the CServiceX25 class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "resource.h"
#include "ServiceX25.h"
#include "ObjectFactory.h"
#include "defs.h"
#include "ProtocolX25.h"
#include "pvc.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNAMIC(CServiceX25, CServiceBase)


CServiceX25::CServiceX25(HKEY const hKeyRoot, CString const strRegPath, CConfigObject const * const pParent)
			:CServiceBase(hKeyRoot, strRegPath, pParent)
{

	try
	{

		// Get adapter parameters
		AffirmThrow(GetParameters());

		// Solve our identity crisis
		SetIdentity(DXB_REGVAL_LINE_SERVICE_X25);

 		CString szDisplayName;
		AffirmThrow(szDisplayName.LoadString(IDS_X25PvcServiceName));
		SetDisplayName(szDisplayName);

		int nStartChannel = ((CProtocolX25*)pParent)->GetPVCStartChannel();
		// we can only add children if PVC channel counts have been defined
		// in the protocol above us.
		if ( nStartChannel!= 0)
			SetAbility(CConfigObject::ADDCHILD | CConfigObject::DELETECHILD);

		// Get our static config data
		AffirmThrow(GetConfigData());


      // Give birth to our children. Need to read the number of PVC ports existing 
	  // in the registry

	   DWORD dwIndex = 0;
	   TCHAR szbuffer[32];
	   DWORD dwbuffsize = sizeof(szbuffer);
	   PFILETIME lpftime = NULL;
	   while (RegEnumKeyEx(m_hKey,dwIndex,szbuffer,&dwbuffsize,NULL,NULL,NULL,lpftime) ==
		   ERROR_SUCCESS)
	   {
		   m_apChildren.SetAtGrow(dwIndex, NULL);
			
		   AffirmThrow(NewConfigObject(&m_apChildren[dwIndex], CConfigObject::PORT, 
			 DXB_REGVAL_PORT_TYPE_X25, m_hKey, szbuffer, this));      // always Frame
           AffirmThrow(m_apChildren[dwIndex] != NULL);
		   dwIndex++;
		   dwbuffsize = sizeof(szbuffer);
       }
   }
   catch (CAffirmException ae)
   {
   }

}

CServiceX25::~CServiceX25()
{
}


//////////////////////////////////////////////////////////////////////
// UI config methods
//////////////////////////////////////////////////////////////////////

BOOL CServiceX25::AddWizardPages(CConfigWizSheet * const pSheet)
{

    BOOL fSuccess = TRUE;
	DWORD nStart,nCount;
	((CProtocolX25*)GetParent())->GetPVCChannelData(nStart,nCount);
	if (nCount)
		fSuccess = CServiceBase::AddWizardPages(pSheet);
	return fSuccess;
}

CString CServiceX25::GetInformationText(void)
{
	CString strInfo;
	try
	{
		strInfo.Format(IDS_PVCINFO_FMT,((CProtocolX25 *)(GetParent()))->GetConfiguredPVCs());
	}
	catch (CAffirmException ae)
	{
	}

	return strInfo;
}

// pop up new PVC dialog box and allow user to add it.
BOOL CServiceX25::AddChild(void)
{
	BOOL bSuccess = FALSE;

	try
	{
		// ask the parent protocol whether we can add another PVC entry
		if (((CProtocolX25*)GetParent())->AllocPVC())
		{
			// enumerate subkeys to see which one we can use.
			// keys are all numeric and start with 0 and work from there
			CString szPortKey;
			DWORD_PTR dwIndex=0;
	
			do
			{
				szPortKey.Format("%d",dwIndex++);
			}while(RegKeyExists(m_hKey,szPortKey));

			CConfigObject* pChild = NULL;
			AffirmThrow(NewConfigObject(&pChild, CConfigObject::PORT, 
			 DXB_REGVAL_PORT_TYPE_X25, m_hKey, szPortKey, this));      // always Frame
			// Give the user a chance to accept/cancel creation of child
			if (pChild->DoProperties())
			{
				dwIndex = GetChildCount();
				m_apChildren.SetAtGrow(dwIndex,NULL);
				m_apChildren[dwIndex] = pChild;
				bSuccess = TRUE;
			}
			else
			{
				DeleteChild(pChild);
				DeleteConfigObject( &pChild );
			}
		}

	}

	catch(CAffirmException ae)
	{
	}

	return bSuccess;
	
}

BOOL CServiceX25::DeleteChild(CConfigObject const * const pChild)
{
	// inform parent protocol of regaining a PVC count
	((CProtocolX25*)GetParent())->DeAllocPVC();
	CServiceBase::DeleteChild(pChild);
	return TRUE;
}



// some methods that get data from the protocol object and hand it to the caller
DWORD CServiceX25::GetWindowSize() const
{
	return(((CProtocolX25*)GetParent())->GetWindowSize());
}

void CServiceX25::GetPVCChannelData(DWORD& start,DWORD& count) const
{
	((CProtocolX25*)GetParent())->GetPVCChannelData(start,count);
	return;
}

void CServiceX25::GetPacketandWindowData(int& RemWindow,int& RemPacket,int& LocWindow,int& LocPacket) const
{

	((CProtocolX25*)GetParent())->GetPacketandWindowData(RemWindow,RemPacket,LocWindow,LocPacket);
	return;
}

// parent protocol has changed. Do a few things to adjust existing PVC's
void CServiceX25::ParentUpdate(void)
{
	CProtocolX25* pParent = (CProtocolX25*)GetParent();
	
	int RemWnd,RemPkt,LocWnd,LocPkt;
	pParent->GetPacketandWindowData(RemWnd,RemPkt,LocWnd,LocPkt);

	DWORD nChannelStart,nChannelCount,nChannelEnd=0;
	pParent->GetPVCChannelData(nChannelStart,nChannelCount);
	int Abilities = CConfigObject::NOABILITIES;
	if (nChannelStart)
	{
		Abilities = CConfigObject::ADDCHILD | CConfigObject::DELETECHILD;
		nChannelEnd = nChannelStart + nChannelCount - 1;
	}
	SetAbility(Abilities);
	
	CConfigObjectArray trash;
	INT_PTR nCount = GetChildCount();
	for(int i=0;i<nCount;i++)
	{
		CPortX25* pChild = (CPortX25*)m_apChildren[i];
		if (!pChild->ValidateChannelRange(nChannelStart,nChannelEnd))
			trash.Add(m_apChildren[i]);
		else
		{
			pChild->SetWindowSize(RemWnd,LocWnd);
		}
	}
	// delete the trash array.
	for(i=0;i<trash.GetSize();i++)
		DeleteChild(trash[i]);
	trash.RemoveAll();

		
}