/*-------------------------------------------------------------------------
 * clintlib\FTPSession.h
 * 
 * Example usage of this code can be found at the bottom of this file.
 *
 * IFTPSession allows you to easily transfer files from an FTP 
 * site while hiding the low level aspects of the Windows FTP API.
 *
 * IFTPSessionUpdateSink is used to receiving information about a transfer.
 *
 * Currently only downloading is supported.
 *
 *
 * Owner: 
 * 
 * Copyright 1986-2000 Microsoft Corporation, All Rights Reserved
 *-----------------------------------------------------------------------*/


//
//  IFTPSessionUpdateSink is used to receive events about the transfer.  
//  You don't have to use it--not even for getting error messages.
//  GetLastErrorMessage() also can be used to get error messages.
//
class IInternetSessionSink
{
public:
    /*-------------------------------------------------------------------------
     * OnProgress()
     *-------------------------------------------------------------------------
     * Purpose:
     *      Report the progress of a transfer.
     *
     * Paramters:
     *      cTotalBytes: Total bytes of the all files in the transfer.
     *
     *      szCurrentFile: Name of the current file being transfered.
     *
     *      cCurrentFileBytes: Count of bytes currently transfered for the current file.
     *
     * Remarks:
     *
     *      Updates occur at the start of the transfer, when a file finishes, and at 8k intervals
     *      during large file transfers.  The 8k interval is determined by Windows and subject to change.
     *
     */
    virtual void OnProgress(unsigned long cTotalBytes, const char* szCurrentFile, unsigned long cCurrentFileBytes) {}

    /*-------------------------------------------------------------------------
     * OnProgress()
     *-------------------------------------------------------------------------
     * Purpose:
     *      Report error occuring during transfer.
     *
     * Paramters:
     *      szErrorMessage: Error message.  Could be long and detailed.
     */
    virtual void OnError(char *szErrorMessage) {}

    /*-------------------------------------------------------------------------
     * OnDataReceived()
     *-------------------------------------------------------------------------
     * Purpose:
     *      Allow user to scan or change data as it comes in; and skip this 
     *      file if wanted.  
     *
     * Paramters:
     *      pData:  pointer to file data chunk
     *      cBytes: size of data chunk
     *
     * Returns:
     *      true: if you want this file's transfer to continue, false to start
     *      next file.
     */
    virtual bool OnDataReceived(void * pData, unsigned long cBytes) { return true; }

    /*-------------------------------------------------------------------------
     * OnFileCompleted()
     *-------------------------------------------------------------------------
     * Purpose:
     *      Signal that another file is transfered and written to disk with no errors.  
     *
     * Paramters:
     *      szFileName: filename of transfered file with complete local path.  
     *
     * Returns:
     *      true:  if file downloaded okay
     *      false: if file should be re-downloaded (sometimes http downloads fail, so you might want to retry)
     */
    virtual bool OnFileCompleted(char *szFileName) 
    {
        return true;
    }

    /*-------------------------------------------------------------------------
     * OnTransferComplete()
     *-------------------------------------------------------------------------
     * Purpose:
     *      Singal that the entire transfer is over.  This is also called in the event
     * of an error (or manual abort) stops the transfer.
     */
    virtual void OnTransferFinished() {}

};


class IHTTPSessionSink :
public IInternetSessionSink
{
};

class IFTPSessionUpdateSink :
public IInternetSessionSink
{
};



class IInternetSessionBase
{
public:
    virtual ~IInternetSessionBase() {}

    /*-------------------------------------------------------------------------
     * ContinueDownload()
     *-------------------------------------------------------------------------
     * Purpose:         
     *    Find out if any errors or events occured during the download.  
     *    Start downloading the next file if done with current one.
     *    Fire events as needed.
     *
     * Returns:
     *    false if aborted, or error, or successful download; true if download
     *    is incomplete and needs to be continued.
     *
     * Remarks:
     *    Errors (and other events) are reported to the Sink.
     */
    virtual bool  ContinueDownload() = 0;


    /*-------------------------------------------------------------------------
     * GetLastErrorMessage()
     *-------------------------------------------------------------------------
     * Returns:
     *    Last error message or NULL if no errors have occured.
     *
     * Remarks:
     *    Errors also are reported to the Sink.
     */               
    virtual const char* GetLastErrorMessage() = 0; // TODO: make this report the error code too


    /*-------------------------------------------------------------------------
     * GetDownloadPath()
     *-------------------------------------------------------------------------
     *
     * Returns a path of where the downloaded files are going.  Guarenteed to
     * end with a backslash.
     */
    virtual const char* GetDownloadPath() = 0; 

    /*-------------------------------------------------------------------------
     * Abort()
     *-------------------------------------------------------------------------
     * Purpose:
     *    Abort the download.
     *
     * Parameters:
     *    bDisconnect: if true, the disconnect is automatic
     */
    virtual void Abort(bool bAutoDisconnect = true) = 0; 
};

class IFTPSession :
    public IInternetSessionBase
{
public:
    virtual ~IFTPSession() {}

    /*-------------------------------------------------------------------------
     * ConnectToSite()
     *-------------------------------------------------------------------------
     * Paramters:
     *    szFTPSite:    FTP address of the server to connect to
     *    szDirectory:  The directory on the server where transfers will occur from
     *
     * Returns:
     *    true if success; false if error
     *
     * Remarks:
     *    Errors are reported to the Sink.
     */
    virtual bool  ConnectToSite(const char *szFTPSite, 
                                const char *szDirectory, 
                                const char *szUsername, 
                                const char *szPassword) = 0; 


    /*-------------------------------------------------------------------------
     * InitiateDownload()
     *-------------------------------------------------------------------------
     * Purpose:         
     *    Begin downloading a batch of files.  You must call ContinueDownload()
     *    periodically to ensure file(s) get downloaded.
     *
     * Paramters:
     *    pszFileList:  A list of files to download.  This is a pointer to a
     *                  NULL terminated array of NULL terminated char pointers.  
     *
     *    szDestFolder: The directory on the local machine of where the files go
     *
     *    bDisconnectWhenDone: if true, session automatically disconnects when done
     *
     *    nMaxBufferSize: maximum amount of memory allocated for download buffer
     *
     * Returns:
     *    true if success; false if error
     *
     * Remarks:
     *    Errors are reported to the Sink.
     */
    virtual bool  InitiateDownload(const char * const * pszFileList, 
                                   const char * szDestFolder, 
                                   bool bDisconnectWhenDone = true,
                                   int nMaxBufferSize = 1024*1024) = 0;

    /*-------------------------------------------------------------------------
     * Disconnect()
     *-------------------------------------------------------------------------
     * Purpose:
     *    Disconnect from FTP server.
     *
     * Returns:
     *    true if success; false if error
     *
     * Remarks:
     *    Errors are reported to the Sink.
     */
    virtual bool Disconnect() = 0; 
};

class IHTTPSession :
    public IInternetSessionBase
{
public:
    virtual ~IHTTPSession() {}

    /*-------------------------------------------------------------------------
     * InitiateDownload()
     *-------------------------------------------------------------------------
     * Purpose:         
     *    Begin downloading a batch of files.  You must call ContinueDownload()
     *    periodically to ensure file(s) get downloaded.
     *
     * Paramters:
     *    pszFileList:  A list of files to download.  This is a pointer to a
     *                  NULL terminated array of NULL terminated char pointers.  
     *                  Each entry is a pair: the first is the URL, the second
     *                  is the local filename
     *
     *    szDestFolder: The directory on the local machine of where the files go
     *
     *    nMaxBufferSize: maximum amount of memory allocated for download buffer
     *
     * Returns:
     *    true if success; false if error
     *
     * Remarks:
     *    Errors are reported to the Sink.
     */
    virtual bool  InitiateDownload(const char * const * pszFileList, 
                                   const char * szDestFolder, 
                                   int nMaxBufferSize = 1024*1024) = 0;

};


IFTPSession * CreateFTPSession(IFTPSessionUpdateSink * pUpdateSink = NULL); // use this to make a new IFTPTransfer object


IHTTPSession * CreateHTTPSession(IHTTPSessionSink * pUpdateSink = NULL);




/*         SAMPLE CODE:

#include "stdafx.h"
#include "FTPSession.h"


class CFTPStatusClass :
    public IFTPSessionUpdateSink
{
public:

    void OnProgress(unsigned long cTotalBytes, const char* szCurrentFile, unsigned long cCurrentFileBytes) 
    {
        char sz[80];
        const int cEstimatedSize = 900;

        sprintf(sz, "%2.2f%%   %i  %s  %i\n", 100.0f*float(cTotalBytes)/float(cEstimatedSize), cTotalBytes, szCurrentFile, cCurrentFileBytes);
        OutputDebugString(sz);
    }

    void OnError(char *szErrorMessage)
    {
        OutputDebugString("\nError:\n");
        OutputDebugString(szErrorMessage);
    }
};


int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
    CFTPStatusClass errorClass;

    IFTPSession *pFTP = CreateFTPSession(&errorClass);

    if (pFTP->ConnectToSite("a-markcu1", "Allegiance", "Anonymous", "Marco"))
    {
        char *pszFileList[] = {"test.vbs", "chat.vbs", "events.vbs", NULL};

        if (pFTP->InitiateDownload(pszFileList, "C:\\temp"))
        {
            while (pFTP->ContinueDownload())
            {
            }
        }
    }

    delete pFTP;

	return 0;
}

*/