// This code is a part of the Telephony Framework C++ Library.
// Copyright (C) 1997 Chris Sells. All rights reserved.
// tLine.h: CtLine interface

#ifndef TLINE_H
#define TLINE_H

#include "tRepTarg.h"       // CtReplyTarget
#include "tLineSink.h"      // CtLineSink
#include "tAppSink.h"       // CtAppSink
#include "tRequestList.h"   // CtRequestList
#include "TFXSTL.h"

/////////////////////////////////////////////////////////////////////////////
// Line Requests

// NOTE: Change the CtLine::OnReplay() implementation when adding values here
// LINEREQUEST_UNKNOWN == CALLEREQUEST_UNKNOWN == ADDRREQUEST_UNKNOWN
#define LINEREQUEST_UNKNOWN 0
#define LINEREQUEST_FORWARD 1

class CtLine : public CtReplyTarget
{
public:
    // Operations
    CtLine();
    virtual ~CtLine();

    HLINE   GetHandle() const;
    DWORD   GetDeviceID() const;

    // Can have multiple sinks per object and they stay around for the
    // life of the object (which may be different than the life of the handle).
    void    AddSink(CtLineSink* pSink);
    void    RemoveSink(CtLineSink* pSink);

    BOOL    IsRequestPending(TREQUEST nRequestID = 0,
                             DWORD* pnRequestType = 0) const;
    BOOL    IsRequestTypePending(DWORD nRequestType) const;

    static CtLine*  FromHandle(HLINE hLine);
    static DWORD    GetNumDevs();
    static HLINEAPP GetAppHandle();
	static DWORD	GetAppVersion();
    static void     SetAppVersion(DWORD dwLoVersion, DWORD dwHiVersion);
    static DWORD    GetApiVersion(DWORD nLineID);

    // Static TAPI wrappers
    static TRESULT  Initialize(CtAppSink* pAppSink, LPCSTR szAppName, HINSTANCE hInst);
    static TRESULT  Shutdown();
    static TRESULT  GetMakeCallRequest(LPLINEREQMAKECALL plmc);
    static TRESULT  GetMediaCallRequest(LPLINEREQMEDIACALL plmc);
    static TRESULT  RegisterRequestRecipient(DWORD dwRegisterMode, BOOL bEnable);
    static TRESULT  TranslateDialog(DWORD nLineID, HWND hwndOwner, LPCSTR szAddressIn);
    static TRESULT  ConfigDialog(DWORD nLineID, HWND hwndOwner, LPCSTR pszDeviceClass = 0);
    static TRESULT  GetIcon(DWORD nLineID, LPHICON phicon, LPCSTR pszDeviceClass = 0);
    static TRESULT  SetCurrentLocation(DWORD nLocationID);

    // TAPI wrappers
    TRESULT Open(DWORD nLineID, CtLineSink* pInitialSink = 0,
                 DWORD dwPriviledges = LINECALLPRIVILEGE_NONE,
                 DWORD dwMediaModes = LINEMEDIAMODE_INTERACTIVEVOICE);
    TRESULT Close();
    TRESULT GetAddressID(LPDWORD pdwAddressID, DWORD nAddressMode, LPCSTR pszAddress, DWORD nSize) const;

    TRESULT GetNumRings(DWORD nAddressID, DWORD* pnRings);
    TRESULT SetNumRings(DWORD nAddressID, DWORD nRings);

    tfxasync TRESULT    ForwardAll(LPLINEFORWARDLIST const plfl, DWORD nRings);
    tfxasync TRESULT    ForwardAddress(DWORD nAddressID, LPLINEFORWARDLIST const plfl, DWORD nRings);

protected:
    // Versions negotiation
    static void NegotiateApiVersions();

    // Line manager
    static void AddToLines(CtLine* pLine);
    static void RemoveFromLines(CtLine* pLine);

    // Static CtLine events
    static void OnCreate(DWORD nLineID);
    static void OnRequest(DWORD nRequestMode, HWND hRequestWnd, TREQUEST nRequestID);

    // CtLine event manager
    virtual void    OnEvent(DWORD hDevice, DWORD nMsg, DWORD dwParam1, DWORD dwParam2, DWORD dwParam3);
    
    // CtLine events
    virtual void    OnAddressState(DWORD nAddressID, DWORD nAddressState);
    virtual void    OnClose();
    virtual void    OnDevSpecific(DWORD dwDevice, DWORD dwParam1, DWORD dwParam2, DWORD dwParam3);
    virtual void    OnDevSpecificFeature(DWORD dwDevice, DWORD dwParam1, DWORD dwParam2, DWORD dwParam3);
    virtual void    OnDevState(DWORD nDevState, DWORD dwParam2, DWORD dwParam3);

    // CtLine events to be routed to CtCall
    virtual void    OnCallInfo(HCALL hCall, DWORD nCallInfo);
    virtual void    OnCallState(HCALL hCall, DWORD nCallState, DWORD dwParam2, DWORD nCallPriviledge);
    virtual void    OnNewCall(DWORD nAddressID, HCALL hCall, DWORD nCallPriviledge);
    virtual void    OnGatherDigits(HCALL hCall, DWORD nGatherTerm);
    virtual void    OnGenerate(HCALL hCall, DWORD nGenerateTerm);
    virtual void    OnMonitorDigits(HCALL hCall, char cDigit, DWORD nDigitMode);
    virtual void    OnMonitorMedia(HCALL hCall, DWORD nMediaMode);
    virtual void    OnMonitorTone(HCALL hCall, DWORD dwAppSpecific);

#if (TAPI_CURRENT_VERSION >= 0x00020000)
    virtual void    OnAgentSpecific(DWORD dwAgentExtensionIDIndex, DWORD dwHandlerSpecific1, DWORD dwHandlerSpecific2);
    virtual void    OnAgentStatus(DWORD nAddressID, DWORD nAgentStatus, DWORD dwAgentStatusDetail);
    virtual void    OnProxyRequest(LINEPROXYREQUEST* pProxyRequest);
    virtual void    OnLineRemove(DWORD dwDeviceID);
#endif

    // CtReplyTarget event
    virtual void    OnReply(TREQUEST nRequestID, TREQUEST nResult, DWORD nRequestType);

    // Telephony event callback
    friend void CALLBACK
    TfxLineCallback(DWORD dwDevice, DWORD nMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2, DWORD dwParam3);

private:
    static CPointerList     s_listLines;
    static HLINEAPP     s_hLineApp;
    static DWORD        s_dwLoVersion;
    static DWORD        s_dwHiVersion;
    static DWORD        s_nNumDevs;
    static CtAppSink*   s_pAppSink;
    static DWORD*       s_aApiVersions;

    HLINE           m_hLine;
    CPointerArray       m_rgSinks;
    DWORD           m_nLineID;
    CtRequestList   m_listRequests;
    CPointerList        m_listUnhandledCalls;

    friend class CtCall;

    // For our own use and the use of our friend, the CtCall
    void AddRequest(TREQUEST nRequestID, CtReplyTarget* pTarget,
                    DWORD dwRequestType);
    void RemoveAllRequests(CtReplyTarget* pTarget = 0);
    BOOL IsCallRequestPending(TREQUEST nRequestID,
                              DWORD* pnRequestType) const;
    BOOL IsCallRequestTypePending(const CtCall* pCall,
                                  DWORD nRequestType) const;

    // Copy constructor and operator= not allowed
private:
    CtLine(const CtLine&);
    CtLine& operator=(const CtLine&);
};

#endif  // TLINE_H
