/////////////////////////////////////////////////////////////////////////////
//
//       
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"

#include <afxpriv.h>

#include "CBaseEvent.h"
 
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//-------------------------------------------------------------------------------
//  
// ---
CObList & CBaseEvent::m_EventList = * new CObList();



/////////////////////////////////////////////////////////////////////////////
//
//      
//
/////////////////////////////////////////////////////////////////////////////
//-------------------------------------------------------------------------------
//
// ---
CBaseEvent::CBaseEvent( int ifType, reference p, long objType, reference doc ) 
  : CCmdTarget(   ),  
    m_dwCookie( 0 ),
    refDoc( doc )
{
  ::memset( &m_params, 0, sizeof(NotifyConnectionParam) );
  m_params.pContainer = p;
  m_params.ifType     = ifType;
  m_params.objType    = objType;
  m_EventList.AddTail( this ); 
}


//-------------------------------------------------------------------------------
// 
// ---
CBaseEvent::CBaseEvent( int ifType, LPUNKNOWN iContainer, long objType, LPUNKNOWN iObj, reference doc )
  : CCmdTarget(   ),  
    m_dwCookie( 0 ),
    refDoc( doc )
{
  ::memset( &m_params, 0, sizeof(NotifyConnectionParam) );
  m_params.pContainer = doc;
  m_params.ifType     = ifType;
  m_params.iContainer = iContainer;
  m_params.objType    = objType;
  m_params.iObj       = iObj;

  if ( m_params.iContainer )
    m_params.iContainer->AddRef();

  if ( m_params.iObj )
    m_params.iObj->AddRef(); 

  m_EventList.AddTail( this ); 
}


//-------------------------------------------------------------------------------
// 
// ---
CBaseEvent::~CBaseEvent()
{
  RemoveThis();  //      
}


//-------------------------------------------------------------------------------
//    
// ---
bool CBaseEvent::Advise() 
{
  ASSERT(!m_dwCookie);
  if( !m_dwCookie && m_params.ifType )
  {
		if ( ReturnResult() ) 
    {
      #ifdef _DEBUG
      MessageBoxResult();
      #endif
      ResultNULL();
		}
    LPUNKNOWN obj = GetUnknown();
    m_dwCookie = ::ksConnectionAdvise ( &m_params, obj );
    obj->Release();
    ASSERT(m_dwCookie);
  }
	return !!m_dwCookie;
}


//-----------------------------------------------------------------------------
// 
// ---
void CBaseEvent::Unadvise()
{
  if( m_dwCookie )
  {
    VERIFY( ::ksConnectionUnadvise( &m_params ) ); 
    m_dwCookie = 0; 
  }
}


//-----------------------------------------------------------------------------
//   
// ---
void CBaseEvent::TerminateEvents( long eventType, reference doc, int objType, LPUNKNOWN iObj )
{
	for ( int i = m_EventList.GetCount() - 1; i >= 0; i-- ) 
  {
  	CBaseEvent * evnt = (CBaseEvent *)m_EventList.GetAt( m_EventList.FindIndex(i) );
		if ( evnt && ( !eventType    || eventType == evnt->GetType()        ) 
			        && ( !doc          || doc       == evnt->refDoc           ) 
							&& ( objType == -1 || objType   == evnt->m_params.objType ) 
							&& ( !iObj         || iObj      == evnt->m_params.iObj    ) ) 
    {
								
		    evnt->Disconnect();			//       RemoveAt(pos)
		}
	}
}


//-----------------------------------------------------------------------------
//   
// ---
CBaseEvent * CBaseEvent::FindEvents( long eventType, reference doc, int objType, LPUNKNOWN iObj )
{
  CBaseEvent * res = NULL;
  for ( int i = m_EventList.GetCount() - 1; i >= 0; i-- ) 
  {
	  CBaseEvent * evnt = (CBaseEvent *) m_EventList.GetAt( m_EventList.FindIndex(i) );
	  if (    ( !eventType                                   ||   eventType == evnt->GetType()        ) 
		     && ( ( !doc          && !evnt->refDoc           ) || ( doc       == evnt->refDoc           ) )
			   && ( ( objType == -1 && !evnt->m_params.objType ) || ( objType   == evnt->m_params.objType ) ) 
			   && ( ( !iObj         && !evnt->m_params.iObj    ) || ( iObj      == evnt->m_params.iObj    ) ) ) 
    {
		  res = evnt;			//       RemoveAt(pos)
      break;
		}
	}
	return res;
}


//-----------------------------------------------------------------------------
//   
// ---
void CBaseEvent::TerminateEvents( void )
{
  while ( !m_EventList.IsEmpty() ) 
  {
	  CBaseEvent * headEvent = (CBaseEvent *)m_EventList.RemoveHead();
		headEvent->Disconnect();				//       RemoveAt(pos)
  }
}


//-------------------------------------------------------------------------------
//  
// ---
void CBaseEvent::DestroyList() 
{
  if ( &m_EventList ) 
  {
    delete &m_EventList;
  }
}


//-------------------------------------------------------------------------------
//     
// ---
void CBaseEvent::RemoveThis() 
{
	//      
	POSITION pos = m_EventList.Find(this);
  if ( pos ) 
  { 
  	m_EventList.RemoveAt( pos );
    Unadvise();                           //    
  }
}


//-------------------------------------------------------------------------------
// 
// ---
void CBaseEvent::Clear() 
{
 if ( m_params.iContainer ) 
 {
    m_params.iContainer->Release();
    m_params.iContainer = NULL;
  }

  if ( m_params.iObj ) 
  {
    m_params.iObj->Release();
    m_params.iObj = NULL;
  }
  ::memset( &m_params, 0, sizeof(NotifyConnectionParam) );  
}


//-------------------------------------------------------------------------------
// 
// ---
void CBaseEvent::Disconnect()                    
{
  Unadvise();
  Clear();
  ExternalRelease();
}


//-------------------------------------------------------------------------------
//    
// ---
void AdviseDoc( long pDoc )
{
	if ( !pDoc )
		pDoc = ::ksGetCurrentDocument( 0 );
	else
    ::SetObjParam(pDoc, NULL, 0, DOCUMENT_STATE);
	if ( pDoc ) 
  {
		int docType = ::ksGetDocumentType( pDoc );
	}
}


//-------------------------------------------------------------------------------
//    
// ---
void AdviseDocuments()
{
  // C     
  reference iter = ::CreateIterator( ALL_DOCUMENTS, 0 );
  
  if ( iter ) 
  {
    reference pDoc = ::MoveIterator( iter, 'F' );

    while ( pDoc )
    {
	    AdviseDoc( pDoc );
	    pDoc = ::MoveIterator( iter, 'N' );
    } 
    ::DeleteIterator( iter );
  }
}

