#pragma once

#ifdef UNICODE
#undef UNICODE
#undef _UNICODE
#define UNICODE_DEFINED
#endif

#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
#include "dcmtk/ofstd/ofcond.h"    /* for class OFCondition */
#include "dcmtk/dcmdata/dcxfer.h"  /* for E_TransferSyntax */
#include "dcmtk/dcmnet/dimse.h"    /* for T_DIMSE_BlockingMode */
#include "dcmtk/dcmnet/dcasccfg.h"
#include "dcmtk/ofstd/ofcmdln.h"

#include "csdcm.h"

//#include "SDCMNetBase.h"

#include "SCallback.h"

#ifdef UNICODE_DEFINED
#define UNICODE
#define _UNICODE
#undef UNICODE_DEFINED
#endif

typedef enum _SNETWORK_CONNECTION
{
	SCONNECT_NORMAL = 0,
	SCONNECT_TLS
}SNETWORK_CONNECTION, *PSNETWORK_CONNECTION;

typedef enum _SNETWORK_BLOCK_MODE
{
	SNETWORK_BLOCKING = 0,
	SNETWORK_NONBLOCKING
}SNETWORK_BLOCK_MODE, *PSNETWORK_BLOCK_MODE;

class CSDCMSendImpl
{
public:
	CSDCMSendImpl();
	virtual ~CSDCMSendImpl();

	virtual void Stop();

    OFCondition DIMSE_storeUser(
        T_ASC_Association *assoc, T_ASC_PresentationContextID presId,
        T_DIMSE_C_StoreRQ *request,
        const char *imageFileName, DcmDataset *imageDataSet,
        DIMSE_StoreUserCallback callback, void *callbackData,
        T_DIMSE_BlockingMode blockMode, int timeout,
        T_DIMSE_C_StoreRSP *response,
        DcmDataset **statusDetail,
        T_DIMSE_DetectedCancelParameters *checkForCancelParams,
        long imageFileTotalBytes);

    OFCondition
    DIMSE_sendMessage(
            T_ASC_Association *assoc,
            T_ASC_PresentationContextID presID,
            T_DIMSE_Message *msg,
            DcmDataset *statusDetail,
            DcmDataset *dataObject,
            const char *dataFileName,
            DIMSE_ProgressCallback callback,
            void *callbackContext,
            DcmDataset **commandSet);

	void SetAETitle(OFString strAETitle);
	void SetServerInfo(OFString strServerAETitle, OFString strClientAETitle, OFString strIP, int nPort, int nConnectionType=SCONNECT_NORMAL, int nBlockingMethod=SNETWORK_BLOCKING);
    void SetServerInfo(QString strServerAETitle, QString strClientAETitle, QString strIP, int nPort, int nConnectionType=SCONNECT_NORMAL, int nBlockingMethod=SNETWORK_BLOCKING);

	int InitNetwork(OFString strServerAETitle, OFString strClientAETitle, OFString strHostIP, int nPort, int nConnectType=SCONNECT_NORMAL, int nBlock=SNETWORK_BLOCKING, int nTimeoutDIMSE=0, int nTimeoutACSE=0, E_TransferSyntax networkTransferSyntax = EXS_Unknown);

	//int Send(CSThread* pCallbackThread, int nTimeoutDIMSE=0, int nTimeoutACSE=0, E_TransferSyntax networkTransferSyntax = EXS_Unknown);
    vector<QString> Send(CSCallback* pCallback, int nTimeoutDIMSE = -1, int nTimeoutACSE = -1, E_TransferSyntax networkTransferSyntax = EXS_Unknown);

	void AddImageFilename(OFString strFilename);
	void AddMpegFilename(OFString strFilename);
	
	void ClearFileList();
	void ClearImageFileList();
	void ClearMpegFileList();

	OFBool IsaListMember(OFList<OFString> &lst, OFString &s);
	OFCondition AddStoragePresentationContexts(T_ASC_Parameters *params, OFList<OFString> &sopClasses);

	OFCondition AddPresentationContext(T_ASC_Parameters *params, int presentationContextId, const OFString &abstractSyntax, const OFString &transferSyntax, T_ASC_SC_ROLE proposedRole = ASC_SC_ROLE_DEFAULT);
	OFCondition AddPresentationContext(T_ASC_Parameters *params, int presentationContextId, const OFString &abstractSyntax, const OFList<OFString> &transferSyntaxList, T_ASC_SC_ROLE proposedRole = ASC_SC_ROLE_DEFAULT);

	OFCondition CheckUserIdentityResponse(T_ASC_Parameters *params);

	OFCondition cstore(T_ASC_Association *assoc, const OFString &fname);
	OFCondition storeSCU(T_ASC_Association *assoc, const char *fname);

	void ReplaceSOPInstanceInformation(DcmDataset *dataset);

	OFBool FindSOPClassAndInstanceInFile(const char *fname, char *sopClass, char *sopInstance);

	static void ProgressCallback(void * callbackData, T_DIMSE_StoreProgress *progress, T_DIMSE_C_StoreRQ * req);
	

	void SetCurrentFilenameList(int nCurrent=0); // 0:NULL, 1:Image, 2:Mpeg

	int GetImageFileCount();
	int GetMpegFileCount();

	void SetLogLevel(int nLevel);

    OFLogger* GetLogger();
protected:
    OFLogger* m_pLoggerStoreSCU;
    CSCallback* m_pCallback;
    //CSDCMNetBase* m_pNetClass;
    //CSThread* m_pCallbackThread;
	OFString m_strHostIP;
	OFString m_strAETitle;
	OFString m_strServerAETitle;
	int m_nPort;
	SNETWORK_CONNECTION m_ConnectType;
	SNETWORK_BLOCK_MODE m_BlockMode;
	E_TransferSyntax m_NetworkTransferSyntax;

	OFList<OFString> m_ImageFileNameList;
	OFList<OFString> m_MpegFileNameList;

	OFList<OFString>* m_pCurrentFileNameList;

	T_ASC_UserIdentityNegotiationMode m_IdentMode;

	OFBool m_bIdentResponse;


	OFBool m_bProposeOnlyRequiredPresentationContexts;
	OFBool m_bCombineProposedTransferSyntaxes;

	int m_nTimeoutACSE;
	int m_nTimeoutDIMSE;

	OFCmdUnsignedInt m_nMaxReceivePDULength;

	T_ASC_Network* m_pNetwork;
	T_ASC_Parameters* m_pNetworkParams;
	DIC_NODENAME m_LocalHost;
	DIC_NODENAME m_PeerHost;
	T_ASC_Association* m_pAssoc;
	DcmAssociationConfiguration m_pAssocConfig;  // handler for association configuration profiles

	int m_nRepeatCount;

	OFBool m_bHaltOnUnsuccessfulStore;
	OFBool m_bUnsuccessfulStoreEncountered;

	E_FileReadMode m_ReadMode;
	OFBool m_bInventSOPInstanceInformation;

	OFBool m_bCorrectUIDPadding;

	T_DIMSE_BlockingMode m_DIMSEBlockMode;

	int m_nLastStatusCode;

	bool m_bAbortAssociation;



    vector<QString> OnDCMSend();
};

