/*****************************************************************************
* 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
*
*****************************************************************************/


// ConfigObject.cpp: implementation of the CConfigObject class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ConfigObject.h"
#include "ObjectFactory.h"

#include "Resource.h"

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

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

IMPLEMENT_DYNAMIC(CConfigObject, CObject)

CConfigObject::CConfigObject(HKEY const hKeyRoot, CString const & strRegPath, CConfigObject const * const pParent)
{
   try
   {
      // TRACE("CConfigObject::CConfigObject(%s), child of %s\n", strRegPath, (pParent != NULL) ? pParent->GetIdentity() : TEXT("Orphaned"));

      AffirmThrow(hKeyRoot != NULL);

      m_hKeyRoot = hKeyRoot;
      m_strRegPath = strRegPath;

      AffirmThrow(RegCreateKey(m_hKeyRoot, m_strRegPath, &m_hKey));
      AffirmThrow(m_hKey != NULL);

      m_pParent = (CConfigObject *)pParent;
      m_strIdentity = TEXT("");
      m_strDisplayName = TEXT("");
      m_eType = UNKNOWN;
      m_eAbility = NOABILITIES;
      m_hDll = NULL;
   }
   catch (CAffirmException)
   {
   }
}

CConfigObject::~CConfigObject()
{
   try
   {
      // TRACE("CConfigObject(%s)::~CConfigObject()\n", GetIdentity());

      // Abort children
      for (int i = 0; i < m_apChildren.GetSize(); i++)
      {
         if (m_apChildren[i] != NULL) DeleteConfigObject(&m_apChildren[i]);
      }

      for (i = 0; i < m_apTrash.GetSize(); i++)
      {
         if (m_apTrash[i] != NULL) DeleteConfigObject(&m_apTrash[i]);
      }

      if (m_hKey != NULL) RegCloseKey(m_hKey);
      m_hKey = NULL;
   }
   catch (CAffirmException)
   {
   }
}

CConfigObject * CConfigObject::GetChild(int const nChild)
{
   CConfigObject * pChild = NULL;

   try
   {
      AffirmThrow(nChild >= 0);
      AffirmThrow(nChild < m_apChildren.GetSize());
      pChild = m_apChildren[nChild];
   }
   catch (CAffirmException ae)
   {
   }

   return pChild;
}

BOOL CConfigObject::DeleteChild(CConfigObject const * const pChild)
{
   BOOL fSuccess = FALSE;

   try
   {
      // TRACE("CConfigObject(%s)::DeleteChild(%s)\n", GetIdentity(), pChild->GetIdentity());

      AffirmThrow(pChild != NULL);

      for (int i = 0; i < m_apChildren.GetSize(); i++)
      {
         if (m_apChildren[i] == pChild)
         {
            // Move the child to the trash array
            m_apTrash.Add(m_apChildren[i]);
            m_apChildren.RemoveAt(i);

            fSuccess = TRUE;
            break;
         }
      }
   }
   catch (CAffirmException ae)
   {
   }

   return fSuccess;
}

BOOL CConfigObject::EmptyTrash(void)
{
   BOOL fSuccess = FALSE;

   try
   {
      for (int i = 0; i < m_apTrash.GetSize(); i++)
      {
         AffirmThrow(m_apTrash[i] != NULL);

         m_apTrash[i]->RemoveParameters(FALSE);
         DeleteConfigObject(&m_apTrash[i]);
      }
      m_apTrash.RemoveAll();

      fSuccess = TRUE;
   }
   catch (CAffirmException ae)
   {
   }

   return fSuccess;
}

BOOL CConfigObject::SetParameters(void)
{
   BOOL fSuccess = FALSE;

   try
   {
      // TRACE("CConfigObject(%s)::SetParameters()\n", GetIdentity());

      AffirmThrow(EmptyTrash());

      // Tell children to write their parameters
      for (int i = 0; i < m_apChildren.GetSize(); i++)
      {
         AffirmThrow(m_apChildren[i] != NULL);
         AffirmThrow(m_apChildren[i]->SetParameters());
      }

      fSuccess = TRUE;
   }
   catch (CAffirmException ae)
   {
   }

   return fSuccess;
}

BOOL CConfigObject::RemoveParameters(BOOL fRemoveKey /* = FALSE */)
{
   BOOL fSuccess = FALSE;

   try
   {
      // TRACE("CConfigObject(%s)::RemoveParameters()\n", GetIdentity());

      AffirmThrow(EmptyTrash());

      for (int i = 0; i < m_apChildren.GetSize(); i++)
      {
         AffirmThrow(m_apChildren[i] != NULL);
         AffirmThrow(m_apChildren[i]->RemoveParameters(fRemoveKey));
      }

      if (fRemoveKey && (m_hKey != NULL))
      {
         RegCloseKey(m_hKey);
         m_hKey = NULL;
         RegDelKey(m_hKeyRoot, m_strRegPath);
      }

      fSuccess = TRUE;
   }
   catch (CAffirmException ae)
   {
   }

   return fSuccess;
}

BOOL CConfigObject::CopyParameters(CConfigObject const * const pFrom)
{
   BOOL fSuccess = FALSE;

   try
   {
      // TRACE("CConfigObject(%s)::CopyParameters(%s)\n", GetIdentity(), pFrom->GetIdentity());

      AffirmThrow(pFrom != NULL);

      AffirmThrow(m_apChildren.GetSize() == pFrom->m_apChildren.GetSize());

      for (int i = 0; i < m_apChildren.GetSize(); i++)
      {
         AffirmThrow(m_apChildren[i] != NULL);
         AffirmThrow(pFrom->m_apChildren[i] != NULL);
         AffirmThrow(m_apChildren[i]->CopyParameters(pFrom->m_apChildren[i]));
      }

      fSuccess = TRUE;
   }
   catch (CAffirmException ae)
   {
   }

   return fSuccess;
}

BOOL CConfigObject::BuildConfigDataRegPath(CString & strRegPath)
{
   BOOL fSuccess = FALSE;

   try
   {
      // TRACE("CConfigObject(%s)::BuildConfigDataRegPath()\n", GetIdentity());

      CConfigObject * pParent = GetParent();

      if (pParent != NULL)
      {
         AffirmThrow(pParent->BuildConfigDataRegPath(strRegPath));
      }
      else
      {
         strRegPath = DXB_REGKEY_CONFIG_DATA;
      }
      
      strRegPath += TEXT("\\") + GetIdentity();

      fSuccess = TRUE;
   }
   catch (CAffirmException ae)
   {
   }

   return fSuccess;
}

BOOL CConfigObject::RemoveWizardPages(CConfigWizSheet * const pSheet)
{
   BOOL fSuccess = FALSE;

   try
   {
      // TRACE("CConfigObject(%s)::RemoveWizardPages()\n", GetIdentity());

      AffirmThrow(pSheet != NULL);

      for (int i = 0; i < m_apChildren.GetSize(); i++)
      {
         AffirmThrow(m_apChildren[i] != NULL);
         AffirmThrow(m_apChildren[i]->RemoveWizardPages(pSheet));
      }

      fSuccess = TRUE;
   }
   catch (CAffirmException ae)
   {
   }

   return fSuccess;
}

BOOL CConfigObject::BuildDisplayTree(CTreeNode * const pNode)
{
   BOOL fSuccess = FALSE;

   try
   {
      // TRACE("CConfigObject(%s)::BuildDisplayTree()\n", GetIdentity());

      AffirmThrow(pNode != NULL);

      pNode->SetDisplayName(GetDisplayName());
      pNode->SetConfigObject(this);

      for (int i = 0; i < m_apChildren.GetSize(); i++)
      {
         CTreeNode Node;

         AffirmThrow(m_apChildren[i] != NULL);
         AffirmThrow(m_apChildren[i]->BuildDisplayTree(&Node));

         pNode->AddBranch(Node);
      }

      fSuccess = TRUE;
   }
   catch (CAffirmException ae)
   {
   }

   return fSuccess;
}

CString CConfigObject::GetInformationText(void)
{
   CString strInfo = TEXT("");

   try
   {
      AffirmThrow(strInfo.LoadString(IDS_Information_None));
   }
   catch (CAffirmException ae)
   {
   }

   return strInfo;
}

// walk all the children until we reach the Service object. Then return the # of
// children (PORTS).
INT_PTR CConfigObject::GetConfiguredPorts(void)
{
	INT_PTR nConfiguredPorts = 0;

	try
	{
		int nType = GetType();

		AffirmThrow(nType != UNKNOWN);
		AffirmThrow(nType != PORT);  // this should never happen. EVER.

		if (nType == SERVICE)
      {
			nConfiguredPorts = GetChildCount();
      }
		else
		{
			for(int i = 0; i < GetChildCount(); i++)
			{
				if (m_apChildren[i] != NULL)
				{
					nConfiguredPorts += m_apChildren[i]->GetConfiguredPorts();
				}
			}
		}
	}
	catch(CAffirmException ae)
	{
	}

	return nConfiguredPorts;
}

BOOL CConfigObject::FindAllMatchingDescendents(SEnumDescendentsCriteria & Criteria)
{
   BOOL fSuccess = FALSE;

   try
   {
      for (int i = 0; i < m_apChildren.GetSize(); i++)
      {
         AffirmThrow(m_apChildren[i] != NULL);

         if (m_apChildren[i]->GetIdentity() == Criteria.strIdToMatch) Criteria.aDescendents.Add(m_apChildren[i]);

         AffirmThrow(m_apChildren[i]->FindAllMatchingDescendents(Criteria));
      }

      fSuccess = TRUE;
   }
   catch (CAffirmException ae)
   {
   }

   return fSuccess;
}

CConfigObject * CConfigObject::EnumDescendents(SEnumDescendentsCriteria & Criteria)
{
   CConfigObject * pDescendent = NULL;

   try
   {
      if (Criteria.iCurrentDescendent < 0)
      {
         AffirmThrow(FindAllMatchingDescendents(Criteria));

         if (Criteria.aDescendents.GetSize() > 0)
         {
            Criteria.iCurrentDescendent = 0;
            pDescendent = Criteria.aDescendents[Criteria.iCurrentDescendent];
         }
      }
      else
      {
         Criteria.iCurrentDescendent++;
         if (Criteria.iCurrentDescendent < Criteria.aDescendents.GetSize())
            pDescendent = Criteria.aDescendents[Criteria.iCurrentDescendent];
      }
   }
   catch (CAffirmException ae)
   {
   }

   return pDescendent;
}
