// tMonitorView.h : interface of the CtMonitorView class
//
/////////////////////////////////////////////////////////////////////////////

#include "ListViewEx.h"
#include "IncomingCallDlg.h"

class CtMonitorView : public CListViewEx,
                      public CtLineSink,
                      public CtCallSink
{
protected: // create from serialization only
	CtMonitorView();
	DECLARE_DYNCREATE(CtMonitorView)

// Attributes
public:
	CtMonitorDoc* GetDocument();

// Operations
public:

// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CtMonitorView)
	public:
	virtual void OnDraw(CDC* pDC);  // overridden to draw this view
	virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
	protected:
	virtual void OnInitialUpdate(); // called first time after construct
	//}}AFX_VIRTUAL

// Implementation
public:
	virtual ~CtMonitorView();
#ifdef _DEBUG
	virtual void AssertValid() const;
	virtual void Dump(CDumpContext& dc) const;
#endif

protected:
    // Override from base class
    LPCSTR  GetColumnText(int nColumn, LPARAM lParam);

// Generated message map functions
protected:
	//{{AFX_MSG(CtMonitorView)
	afx_msg void OnColumnclick(NMHDR* pNMHDR, LRESULT* pResult);
	afx_msg void OnDblclk(NMHDR* pNMHDR, LRESULT* pResult);
	afx_msg void OnDeleteitem(NMHDR* pNMHDR, LRESULT* pResult);
	afx_msg void OnGetdispinfo(NMHDR* pNMHDR, LRESULT* pResult);
	afx_msg void OnReturn(NMHDR* pNMHDR, LRESULT* pResult);
	afx_msg void OnDestroy();
	afx_msg void OnMonitorDial();
	afx_msg void OnUpdateMonitorDial(CCmdUI* pCmdUI);
	afx_msg void OnViewAutosizecolumns();
	afx_msg void OnUpdateViewAutosizecolumns(CCmdUI* pCmdUI);
	afx_msg void OnTimer(UINT nIDEvent);
	afx_msg void OnViewMessages();
	afx_msg void OnMonitorCallScreenSettings();
	afx_msg void OnViewLines();
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()

    int     m_nActiveCalls;
	BOOL    m_bViewInited;
    UINT    m_nTimer;

    struct SORTPARAMS
    {
        int     nColumn;
        BOOL    bAscending;

        SORTPARAMS(int _nColumn, BOOL _bAscending)
            : nColumn(_nColumn), bAscending(_bAscending)
        {}
    }   m_sp;

    // Arranged alphabetically for easy sorting
    struct CALLRECORD
    {
        CString     sName;
        CString     sPhoneNo;
        time_t      tmStart;
        time_t      tmEnd;
        ULONG       nRings;
        ULONG       nMaxRings;
        DWORD       nState;
        CtCall*     pCall;
        BOOL        bInbound;

        CIncomingCallDlg*   pdlg;


        CALLRECORD(LPCSTR pszName, LPCSTR pszPhoneNo, DWORD _nState,
                   CtCall* _pCall, BOOL _bInbound)
        : sName(pszName), sPhoneNo(pszPhoneNo), tmStart(time(0)),
          nRings(1), nMaxRings(0), nState(_nState), pCall(_pCall), tmEnd(0),
          bInbound(_bInbound), pdlg(_bInbound ? new CIncomingCallDlg : 0)
        {
            // If this is an inbound call, put up the dialog
            if( bInbound && pdlg )
            {
                pdlg->m_pCall = pCall;
                pdlg->m_sName = sName;
                pdlg->m_sPhoneNo = sPhoneNo;
                pdlg->DoModeless();

                // Get maximum number of rings for the call
                CtCallInfo  ci;
                if( TSUCCEEDED(ci.GetCallInfo(pCall)) &&
                    TSUCCEEDED(pCall->GetLine()->GetNumRings(ci.GetAddressID(), &nMaxRings)) &&
                    nMaxRings )
                {
                    TRACE1("Answer call after %d rings\n", nMaxRings);
                }
                else
                {
                    TRACE0("Don't answer call automatically\n");
                }
            }
        }

        ~CALLRECORD()
        {
            SetCallIdle();
        }

        void UpdateDialog()
        {
            if( pdlg )
            {
                pdlg->m_sName = sName;
                pdlg->m_sPhoneNo = sPhoneNo;
                pdlg->UpdateData(FALSE);
            }
        }

        long GetDuration()
        { return (tmEnd ? tmEnd : time(0)) - tmStart; }

        void SetCallIdle()
        {
            // End the call duration
            tmEnd = time(0);

            // Close the dialog
            if( pdlg ) pdlg->DestroyWindow();
            delete pdlg;
            pdlg = 0;

            // Delete the call
            delete pCall;
            pCall = 0;
        }
    };

	void    DoDial();
    BOOL    AppendCallRecord(CALLRECORD* pcr);
    BOOL    FindCallRecord(CtCall* pCall, CALLRECORD** ppcr, int* pnItem);
    BOOL    FindCallRecord(CtLine* pLine, CALLRECORD** ppcr, int* pnItem);

    CHeaderCtrl*    GetHeaderCtrl();

    friend int CALLBACK CompareItems(LPARAM, LPARAM, LPARAM);

// Lines
private:
    CtLine* m_rgLines;

    void    OpenValidLines();
    void    MonitorCall(CtLine* pLine, HCALL hCall);
	void    SetNumRings(DWORD nRings);

// Line and Call events of interest
protected:
    virtual void    OnLineNewCall(CtLine* pLine, HCALL hCall, DWORD nAddressID, DWORD nCallPriviledge);
    virtual void    OnLineDevState(CtLine* pLine, DWORD nDevState, DWORD dwParam2, DWORD dwParam3);
    virtual void    OnCallInfo(CtCall* pCall, DWORD nCallInfo);
    virtual void    OnCallState(CtCall* pCall, DWORD nCallState, DWORD dwParam2, DWORD nCallPriviledge);
};

#ifndef _DEBUG  // debug version in tMonitorView.cpp
inline CtMonitorDoc* CtMonitorView::GetDocument()
   { return (CtMonitorDoc*)m_pDocument; }
#endif

/////////////////////////////////////////////////////////////////////////////
