/***************************************************************************
 *                          Zanoza Modeler v2.x                            *
 *      This is unpublished propietary source code of Zanoza Software.     *
 *      The copyright notice does not evidence any actual or intended      *
 *                    publication of such source code.                     *
 *                                                                         *
 *                   Copyright (c) 2002 Zanoza Software.                   *
 *                                                                         *
 *                        All rights reserved.                             *
 ***************************************************************************
 *--------------------------------------------------------------------------
 * @author:   Oleg M.
 *--------------------------------------------------------------------------
 * @purpose:  ZModeler 2.x interface smart pointer
 *--------------------------------------------------------------------------
 * @histroy: 23.09.2002. Created
 * @histroy: 08.02.2006. VS8 compatibility
 */
#ifndef zptr_h_included
#define zptr_h_included
#pragma warning (disable: 4786)

template <class T, class baseT = T>
class ZPtr
{
public:
  T* m_p;
  ZPtr()
  {
    m_p=NULL;
  }
	
  ZPtr(T* lp)
  {
    if ((m_p = lp) != NULL)
      m_p->AddRef();
  }
	
  ZPtr(const ZPtr<T>& lp)
  {
    if ((m_p = lp.m_p) != NULL)
      m_p->AddRef();
  }
	
  ~ZPtr()
  {
    if (m_p!=NULL)
      m_p->Release();
  }
	
  void Release()
  {
    ZUnknown* pTemp = m_p;
    if (pTemp!=NULL)
    {
      m_p = NULL;
      pTemp->Release();
    }
  }
	
  operator T*() const
  {
    return (T*)m_p;
  }

  T& operator*() const
  {
    return *m_p;
  }
  //If you need a T**-result of & operator, take an address of p member explicitly.
  baseT** operator&()
  {
    return reinterpret_cast<baseT**>(&m_p);
  }
	
  T* operator->() const
  {
    return m_p;
  }


  T* operator=(T* lp)
  {
    if (m_p!=NULL)
      m_p->Release();
    m_p=lp;
    if (m_p!=NULL)
      m_p->AddRef();
    return m_p;
  }
	
  T* operator=(const ZPtr<T>& lp)
  {
    if (m_p!=NULL)
      m_p->Release();
    m_p=lp.m_p;
    if (m_p!=NULL)
      m_p->AddRef();
    return m_p;
  }
	
  bool operator!() const
  {
    return (m_p==NULL);
  }
	
  bool operator==(T* pT) const
  {
    return m_p == pT;
  }

  bool operator==(const ZPtr<T>& pT) const
  {
    return m_p == pT.m_p;
  }

  void Attach(T* p2)
  {
    if (m_p)
      m_p->Release();
    m_p = p2;
  }

  T* Detach()
  {
    T* pt = m_p;
    m_p = NULL;
    return pt;
  }

  ZRESULT CopyTo(baseT** ppT)
  {
    if (ppT == NULL)
      return ZRESULT_INVALID_ARG;
    *ppT = m_p;
    if (m_p!=NULL)
    {
      m_p->AddRef();
      return ZRESULT_OK;
    }
    return ZRESULT_FALSE;
  }
};


//--------------------------------
// generic pointer template
//--------------------------------
template <class T>
class ZStdPtr
{
public:
  T* m_p;
  ZStdPtr()
  {
    m_p=NULL;
  }
	
  ZStdPtr(T* lp)
  {
    m_p = lp;
  }
	
  ZStdPtr(const ZStdPtr<T>& lp)
  {
    m_p = lp.m_p;
  }
	
  virtual ~ZStdPtr()
  {
  }
	
  operator T*() const
  {
    return (T*)m_p;
  }

  T& operator*() const
  {
    return *m_p;
  }

  T** operator&()
  {
    return &m_p;
  }
	
  T* operator->() const
  {
    return m_p;
  }


  T* operator= (T* lp)
  {
    return m_p=lp;
  }
	
  T* operator= (const ZStdPtr<T>& lp)
  {
    return m_p=lp.m_p;
  }
	
  bool operator!() const
  {
    return (m_p==NULL);
  }
  /*	
  bool operator==(const T* pT) const
  {
    return m_p == pT;
  }

  bool operator==(const ZStdPtr<T>& lp) const
  {
    return m_p == lp.m_p;
  }
  */
};


//--------------------------------
// generic pointer template that
// owns data and deletes it.
//--------------------------------
template <class T>
class ZStdOwnPtr : public ZStdPtr<T>
{
public:
  ZStdOwnPtr()
  {
    m_p = NULL;
  }
  ZStdOwnPtr(T* lp)
  {
    m_p = lp;
  }
  ZStdOwnPtr(const ZStdPtr<T>& lp)
  {
    m_p = lp.m_p;
  }
  virtual ~ZStdOwnPtr()
  {
    if (m_p != NULL)
      delete m_p;
  }
  T* operator= (T* lp)
  {
    if (m_p == lp)
      return m_p;
    if (NULL != m_p)
      delete m_p;
    return m_p=lp;
  }
  T* operator= (const ZStdOwnPtr<T>& p)
  {
    if (m_p == p.m_p)
      return m_p;
    if (NULL != m_p)
      delete m_p;
    return m_p=p.m_p;
  }
  /*
  bool operator== (const T* lp) const
  {
    return m_p==lp;
  }
  bool operator== (const ZStdOwnPtr<T>& p) const
  {
    return m_p==p.m_p;
  }
  */
};


//--------------------------------
// pointer template to owned CWnd-
// derieved classes. DestroyWindow()
// is used to delete owned wnd
//--------------------------------
template <class T=CWnd>
class ZOwnWndPtr
{
public:
  ZOwnWndPtr()
  {
    m_p = NULL;
  }
  ZOwnWndPtr(T* lp)
  {
    m_p = lp;
  }
  ZOwnWndPtr(const ZOwnWndPtr<T>& lp)
  {
    //do nothing
    m_p = NULL;
  }
  virtual ~ZOwnWndPtr()
  {
    if (m_p != NULL)
      m_p->DestroyWindow();
  }
  operator T*() const
  {
    return (T*)m_p;
  }

  T& operator*() const
  {
    return *m_p;
  }
  //If you need a T**-result of & operator, take an address of p member explicitly.
  T** operator&()
  {
    return &m_p;
  }
	
  T* operator->() const
  {
    return m_p;
  }
  T* operator= (T* lp)
  {
    if (m_p == lp)
      return m_p;
    if (NULL != m_p)
      m_p->DestroyWindow();
    return m_p=lp;
  }
  T* operator= (const ZOwnWndPtr<T>& p)
  {
    if (m_p == p.m_p)
      return m_p;
    if (NULL != m_p)
      m_p->DestroyWindow();
    return m_p=p.m_p;
  }
  bool operator== (const T* lp) const
  {
    return m_p==lp;
  }
  bool operator== (const ZOwnWndPtr<T>& p) const
  {
    return m_p==p.m_p;
  }
  T* Detach()
  {
    T* ptr = m_p;
    m_p = NULL;
    return ptr;
  }
  //
  // data member:
  //
  T* m_p;
};

//--------------------------------
// pointer template for dialog
// items. Wraps GetDlgItem routine
//--------------------------------
template <class T=CWnd>
class ZDlgItemPtr
{
public:
  ZDlgItemPtr()
  {
    m_pDialogWnd = NULL;
    m_p = NULL;
  }
  ZDlgItemPtr(CWnd* pDialogWnd, const long nID = 0)
  {
    m_pDialogWnd = pDialogWnd;
    m_p = (nID == 0) ? NULL : (T*)m_pDialogWnd->GetDlgItem(nID);
  }
  T* operator= (T* lp)
  {
    return m_p=lp;
  }
  T* operator= (const long nID)
  {
    m_p = (nID == 0) ? NULL : (T*)m_pDialogWnd->GetDlgItem(nID);
  }
  T* operator->()
  {
    return m_p;
  }
  operator T*()
  {
    return m_p;
  }
private:
  T*    m_p;
  CWnd* m_pDialogWnd;
};

#define ZDLGITEM(classname, varname, id)  ZDlgItemPtr<classname> varname(this, id);


//--------------------------------
// pointer to linear buffers
//--------------------------------
template <class T>
class ZBufPtr
{
public:
  ZBufPtr()
  {
    m_pBuf = NULL;
  }
  ZBufPtr(T* lp)
  {
    m_pBuf = lp;
  }
  virtual ~ZBufPtr()
  {
    if (NULL != m_pBuf)
      delete[] m_pBuf;
  }
  T* operator= (T* lp)
  {
    if (NULL != m_pBuf)
      delete[] m_pBuf;
    return m_pBuf=lp;
  }
  bool operator!() const
  {
    return (m_pBuf==NULL);
  }
  T* getBuffer()
  {
    return m_pBuf;
  }
  T& operator[](const int i)
  {
    return m_pBuf[i];
  }
  T* Detach()
  {
    T* ptr = m_p;
    m_p = NULL;
    return ptr;
  }
private:
  T*    m_pBuf;
};

#endif //zptr_h_included
