using System;
using System.Text;
using System.Runtime.InteropServices;

namespace HttpFtpDemoNet
{
	/// <summary>
	/// Summary description for HttpFtp.
	/// </summary>
	public class HttpFtp
	{
        // ***************************The kernel whole related interface following********************************

        // ======================================================================================
        // Start-up and Shut-down the kernel interface
        // ======================================================================================
        [DllImport("HttpFtp.dll", EntryPoint="HttpFtp_Startup",  SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
        public static extern Boolean HttpFtp_Startup();

        [DllImport("HttpFtp.dll", EntryPoint="HttpFtp_Shutdown",  SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
        public static extern void HttpFtp_Shutdown();

        // ======================================================================================
        // Setting HttpFtp kernel configuration, all the options can be reference HttpFtpGlobalSetting 
        // ======================================================================================
        // It is setting all at once, if you just want to change one configuration , please call HttpFtp_GetSetting get 	// current setting,then change based on it. (there are instructions in the demo program)
        [DllImport("HttpFtp.dll", EntryPoint="HttpFtp_SetSetting",  SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
        public static extern void HttpFtp_SetSetting (HttpFtpGlobalSetting  s);

        [DllImport("HttpFtp.dll", EntryPoint="HttpFtp_GetSetting",  SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
        public static extern void HttpFtp_GetSetting (ref HttpFtpGlobalSetting setting);


        //Several Traffic Limit interface 
        [DllImport("HttpFtp.dll", EntryPoint="HttpFtp_SetMaxTraffic",  SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
        public static extern void HttpFtp_SetMaxTraffic (UInt32 uTrafficLimit);      //Maximum kernel 

        [DllImport("HttpFtp.dll", EntryPoint="HttpFtp_SetMaxConns",  SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
        public static extern void HttpFtp_SetMaxConns (UInt32 uMaxConns);            //Maxinum connections 

        [DllImport("HttpFtp.dll", EntryPoint="HttpFtp_SetMaxConnsPS",  SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
        public static extern void HttpFtp_SetMaxConnsPS (UInt32 uMaxConnsPS);        //Max connections in a single server


        // ======================================================================================
        // Setting HttpFtp kernel proxy
        // ======================================================================================
        [DllImport("HttpFtp.dll", EntryPoint="HttpFtp_SetProxy",  SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
        public static extern int HttpFtp_SetProxy (
            HttpFtp_ACCESS_TYPE       proxyType,   // Set to use IE proxy¡¢don't use the proxy  or setting proxy manually,
						  // default is not use proxy
            //  The following parameters only effective when proxyType is HttpFtp_ACCESS_MANUAL(manually setting mode) 
            int		  proxyTo,	   // Which download type use proxy settings reference HttpFtpLib_PROXY_TO_HTTP
            string    proxyUrl,    // Proxy server site (including port), for example:http://198.20.31.85:8080
            string    userName,    // user name for authorization
            string    password     // password for authorization
            );

        // ======================================================================================
        //  Setting what language HttpFtp kernel output use, at present only English and Chinese can choose,
		// default is english
        // ======================================================================================
        [DllImport("HttpFtp.dll", EntryPoint="HttpFtp_SetLogLanguage",  SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
        public static extern void HttpFtp_SetLogLanguage (HttpFtp_LANG_TYPE langType);


        // ======================================================================================
        // Setting callback function of receive HttpFtp kernel output, if you don't need download information you can not set         // this function
        // ======================================================================================
        [DllImport("HttpFtp.dll", EntryPoint="HttpFtp_SetReceiveLogFunc",  SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
        public static extern void HttpFtp_SetReceiveLogFunc (
            [MarshalAs(UnmanagedType.FunctionPtr)]  HttpFtp_RECEIVELOG_CALLBACK         pfn,        // callback function pointer
            IntPtr                              lpParam     // Upload a record context (optional), if have uploaded, it would back to the caller intact when callback.
            );

        // ***************************  The relevant interface about single download following********************************

        // ======================================================================================
        // Start a download task
        // ======================================================================================
        [DllImport("HttpFtp.dll", EntryPoint="HttpFtp_Downloader_Initialize",  SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
        public static extern int HttpFtp_Downloader_Initialize (
            HttpFtpDownloaderParams                 httpParams,         // Start download parameters (a url and save directory)
            ref int                                 downloaderID,   // Returns a downloader ID, in order to identify the task (get download schedule etc)
            ref HttpFtpDownloaderAdditionalParams   additionalParams // Additional parameters,such as setting refer,etc
            );

        // ======================================================================================
        // If task has been downloaded a part last time, you must specify last saved download path(status file)
		// and the configuration consistent with last time to make sure it can download in broken-point connection instability mode
        // ======================================================================================
        //
        [DllImport("HttpFtp.dll", EntryPoint="HttpFtp_Downloader_Load",  SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
        public static extern int HttpFtp_Downloader_Load (
            ref int       downloaderID,     // Returns a downloader ID, in order to identify the task (get download schedule etc)
            string        statusFile        // The status file path (for broken-point Connection instability) to continuing, otherwise it is a new download
            );   

        // ------------  Several common operation function following
        // ======================================================================================
        //  When stop download, the task downloader ID still valid, use it can query file size and download completion status, etc
		//  dwMilliseconds: The longest waiting time, if it is "0" return immediately,if it is INFINITE, express wait until all the operation stop (each thread)
		//  Return the result: 0:stopped  1:stopping, but not yet completed, other return values are windows error.
        // ======================================================================================
        [DllImport("HttpFtp.dll", EntryPoint="HttpFtp_Downloader_Stop",  SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
        public static extern int HttpFtp_Downloader_Stop (int downloaderID, int dwMilliseconds);

        // ======================================================================================
		//  If remove download task, the task downloader ID will no longer valid, then all resources are released
		//  iDeleteFiles: 0: no deleting files, just stop; 1:just delete status file; 2:delete all (include the files just downloaded)
        // ======================================================================================
        [DllImport("HttpFtp.dll", EntryPoint="HttpFtp_Downloader_Release",  SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
        public static extern int HttpFtp_Downloader_Release (int downloaderID, int iDeleteFiles);

        // ======================================================================================
        // If you need continue a task that stopped or paused,  you can call this function to continue
        // ======================================================================================
        [DllImport("HttpFtp.dll", EntryPoint="HttpFtp_Downloader_Resume",  SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]    
        public static extern int HttpFtp_Downloader_Resume (int downloaderID);

        // ======================================================================================
        // Add mirror site for a task(a file may download from multiple servers simultaneously)
        // ======================================================================================
        [DllImport("HttpFtp.dll", EntryPoint="HttpFtp_Downloader_AddMirrorUrl",  SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]    
        public static extern int HttpFtp_Downloader_AddMirrorUrl (int downloaderID, string url);

        // ======================================================================================
        // Several common function used to obtain message following
        // ======================================================================================

        // Get download file name (if the file is named automatically, the value returned may be empty before the task got the real file name) 
        [DllImport("HttpFtp.dll", EntryPoint="HttpFtp_Downloader_GetFileName",  SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
        public static extern string HttpFtp_Downloader_GetFileName (int downloaderID);
            
        // Get download speed (Byte per second B/s)
        [DllImport("HttpFtp.dll", EntryPoint="HttpFtp_Downloader_GetSpeed",  SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
        public static extern int HttpFtp_Downloader_GetSpeed (int downloaderID);
            
        // Get left time estimated by the current speed
        [DllImport("HttpFtp.dll", EntryPoint="HttpFtp_Downloader_GetLeftTime",  SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
        public static extern int HttpFtp_Downloader_GetLeftTime (int downloaderID);

        // Get current download percent
        [DllImport("HttpFtp.dll", EntryPoint="HttpFtp_Downloader_GetPercentDone",  SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
        public static extern float HttpFtp_Downloader_GetPercentDone (int downloaderID);
            
        // Get file total size (Byte)
        [DllImport("HttpFtp.dll", EntryPoint="HttpFtp_Downloader_GetFileSize",  SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
        public static extern UInt64 HttpFtp_Downloader_GetFileSize (int downloaderID);
            
        // Get the data size (Byte) have downloaded
        [DllImport("HttpFtp.dll", EntryPoint="HttpFtp_Downloader_GetDownloadedSize",  SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
        public static extern UInt64 HttpFtp_Downloader_GetDownloadedSize (int downloaderID);
            
        // Get left size (Byte)
        [DllImport("HttpFtp.dll", EntryPoint="HttpFtp_Downloader_GetLeftSize",  SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
        public static extern UInt64 HttpFtp_Downloader_GetLeftSize (int downloaderID);

        // Get task status: downloading, pause and finished etc
        [DllImport("HttpFtp.dll", EntryPoint="HttpFtp_Downloader_GetState",  SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
        public static extern HttpFtp_DOWNLOADER_STATE HttpFtp_Downloader_GetState (int downloaderID);

        // Check error message 
        [DllImport("HttpFtp.dll", EntryPoint="HttpFtp_Downloader_GetLastError",  SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
        public static extern int HttpFtp_Downloader_GetLastError (int downloaderID);

        // The relative interface to verify authorised edition
        [DllImport("HttpFtp.dll", EntryPoint="HttpFtp_SetVerInfo",  SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
        public static extern void HttpFtp_SetVerInfo (int cert1, int cert2, int cert3, string cert4);         



        //////////////////////// Type definition following: type.h //////////////////////////////////////////////////////
        ///
        // *********************************  Some global set following **********************************************
        
        //Some FTP transmission way setting
        public enum HttpFtp_FtpTransferType
        {
            FTT_BINARY,		//Binary mode
            FTT_ASCII,		//ASSII mode
            FTT_BY_EXT,		//Select download pattern according to filename extension(only the file in ftpASCIIExt use ASCII mode,else use binary mode)
            FTT_NO_SET      //Don't setting,if afferent parameters in alone task,stand for use the global setting but use ByEXT in whole situation
        };

        // =============================================================
		// The vast majority of configuration options about program whole properties in following structure.
		// You can only need change a place when need change.
        // =============================================================
        [StructLayout(LayoutKind.Sequential)]
        public struct HttpFtpGlobalSetting
        {
            // Some basic setting
            public UInt32           maxSections;    // Maximum sections(splits files into several sections and every section start a thread),	
													//default is 12. When one section is  download over,the thread will separate one section from not download data if the remain
													//date(larger than sectionMinSize)are enough for divide into one section, so it can maintain 12 sections throughout until
													//remain data is over or less than sectionMinSize.			
            public UInt32           sectionMinSize; // The minimum section size(Byte).reference the illustrate about maxSections.
            public UInt32           trafficLimit;   // Traffic limitation  
            // 
            public int             dwWriteCaceSize; // Cache size of write (Byte)
            public UInt32          iAutoSaveInterval;  // Save internal(ms) the cache write to disk.
            public Boolean         bReserveDiskSpace;  // Reserve file space before download

            public UInt32           maxAttempts;    // Max number of attempts when error,default is 20.
            public UInt32           retriesTime;    // Period between the next connection attempts(sec)
            public UInt32           nTimeout;       // Connect timeout(sec)

            public Boolean         bUseDetailLog;      // Use the most detailed log (debug),default is using basic message.
            public Boolean         bHideFileNotComplete; // whether set hidden attribute for uncompleted download,default is unhidden.
            public Boolean         bUseServerTime;       // Whether set file date identical to the server after downloaded,default is use download time.
            public Boolean         bReWriteExistFile;    //  Whether replace samename file.It will be ignored on state of broken-point Connection instability.
														 // This parameter is only effect on beginning  download.If the parameter is FALSE£¬it can establish another filename(like name(1)) automatically.    

            // Set the mirror accelerate function: It can search which server have the same file, and download it automatically. 
            public Boolean         bAutoSearchMirror;    // Whether search the file on other servers via mirror server in order to accelerate, default is not use.   
            public int             mirroServer;          // Which mirror server select, 0:FileSearching.com; 1:FindFiles.com. default is 0.
            public UInt32          mirroMinFileSize;     // If the file size is less than the mirroMinFileSize(1M),not use mirror

            // Related setting about download protocol
            public ushort          rollBackSize;    // Size of rollback on broken connections(Byte).

            public Boolean         bFtpUsePassiveMode; // FTP use passive mode.
            public Boolean         bUseHttp11;     //Http protocol use Http1.1.
            public Boolean         bUseCookie;     //Http use Cookie   

            public HttpFtp_FtpTransferType  ftpTransferType;    //Three mode of FTP transmission(Binary systerm¡¢ASCII¡¢according to expanded-name ),default is according to expanded-name.
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public string          ftpASCIIExt;           //  Effect on mode FTT_BY_EXT,Ftp transmission use ASCII mode for these expanded-name file,default is"txt htm html shtml",
														  // between the default name have a blank space,other use Binary system.
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2048)]
            public string          agentStr; 

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
            public string          additionalExtension;    // Additional file extension for uncompleted download,default is not use suffix.
            public void Init ()
            {       
                maxSections = 12;
                sectionMinSize = 300*1024;
                trafficLimit = UInt32.MaxValue;

                dwWriteCaceSize = 2*1024*1024;
                iAutoSaveInterval = 20*1000;
                bReserveDiskSpace = false;

                maxAttempts = 20;
                retriesTime = 5000;        
                nTimeout = 120000;

                bUseDetailLog = false;
                bHideFileNotComplete = false;
                bUseServerTime = false;
                bReWriteExistFile = true;

                bAutoSearchMirror = false;
                mirroServer = 0;
                mirroMinFileSize = 1000 * 1024;

                rollBackSize = 3500;

                bFtpUsePassiveMode = true;
                bUseHttp11 = true;
                bUseCookie = true;

                ftpTransferType = HttpFtp_FtpTransferType.FTT_BY_EXT;   

                ftpASCIIExt = "txt htm html shtml";
                agentStr = @"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)"; 
            }

        };


        // ========================================================================================
        // Detailed log setting,at present, only English and Chinese can be chosen,default is English.
        // ========================================================================================
        public enum HttpFtp_LANG_TYPE
        {
            HttpFtp_LANG_EN,
            HttpFtp_LANG_CHS
        };

        // ========================================================================================
        // This is the callback function used for get detailed log, 
		// when ever there is an message, it will inform through this function immediately.
        // ========================================================================================
        //[UnmanagedFunctionPointer(CallingConvention.Cdecl)]            
        public delegate void HttpFtp_RECEIVELOG_CALLBACK(int dwonloaderID, [MarshalAs(UnmanagedType.LPStr)] string strLog, IntPtr lpParam);


        // ***************************  Some types about a download task following********************************
        // ========================================================================================
        // A task basic parameter used at start-up.
        // ========================================================================================
        public struct HttpFtpDownloaderParams
        {
            public string      url;                    // Download url (Http or ftp)
            public string      saveFolder;             // Save to which folder
            public string      fileName;               // Filename: If bAutoName is FALSE, then use this filename, else use this fileName when rename failed.

            public Boolean     bAutoName;              // Whether automatic renaming,default is TRUE.
            public void Init()
            {
                bAutoName = true;
            }
        };

        // ========================================================================================
        // Some dowmload task states  
        // ========================================================================================
        public enum HttpFtp_DOWNLOADER_STATE
        {
            HttpFtp_DLSTATE_NONE     = 0,   // intialized
            HttpFtp_DLSTATE_DOWNLOADING,    // dowmloading
            HttpFtp_DLSTATE_PAUSE,          // pause
            HttpFtp_DLSTATE_STOPPED,        // stopped
            HttpFtp_DLSTATE_FAIL,           // failed
            HttpFtp_DLSTATE_DOWNLOADED      // finished
        };

        // ========================================================================================
        // Some setting about proxy following 
        // ========================================================================================

        // Several way of internet: no need of proxy,  using IE proxy Settings,use the defined proxy Settings
        public enum HttpFtp_ACCESS_TYPE	
        {
            HttpFtp_ACCESS_NOPROXY,		// Don't use the proxy: proxyUserName parameters ignored when set this one.
            HttpFtp_ACCESS_IE_CONFIG,   // Use IE proxy Settings:  Some parameters ignored behind 
            HttpFtp_ACCESS_MANUAL		// Use the defined proxy Settings:only this need setting proxyUserName and other paramenters following.							
        }; 

        // The following is only effective in HttpFtp_ACCESS_MANUAL
        public const int HttpFtp_PROXY_TO_HTTP = 1;     // Use proxy only in the way of Http download
        public const int HttpFtp_PROXY_TO_HTTPS = 2;    // Use proxy only in the way of Https download 
        public const int HttpFtp_PROXY_TO_FTP = 4;      // Use proxy only in the way of Ftp download
        public const int HttpFtp_PROXY_TO_ALL = (HttpFtp_PROXY_TO_HTTP | HttpFtp_PROXY_TO_HTTPS | HttpFtp_PROXY_TO_FTP);     //Use proxy for all download type


        // ========================================================================================
        // Some advanced setting of a task.
        // ========================================================================================
        public struct HttpFtpDownloaderAdditionalParams
        {
            public string      statusFile;         // Status file for using in broken-point Connection instability mode
            public string      referer;            // The HTTP protocol refer: Some sites don't allow you download without referer, you can consider use refer to handle
            public string      authUserName;	    // This address needs to identity verification(UserName)
            public string      authPassword;       // This address needs to identity verification(Password)

            public UInt32       maxSections;        // Maximum sections(splits files into several sections and every section start a thread),	
													//default is 12. When one section is  download over,the thread will separate one section from not download data if the remain
													//date(larger than sectionMinSize)are enough for divide into one section, so it can maintain 12 sections throughout until
													//remain data is over or less than sectionMinSize.	

            public UInt32       sectionMinSize; //The minimum section size(Byte).reference maxSections.
												// The default is 0, represent use global Settings and this task is not alone Settings

            public UInt32       trafficLimit;   // Traffic limitation.The default is 0, represent use global Settings.

            public HttpFtp_FtpTransferType  ftpTransferType;    //The mode of FTP transmission(Binary system¡¢ASCII¡¢according to expanded-namedon't setting)default is not setting--use global Settings
            public int         iFtpUsePassiveMode; // The transmission mode of FTP,1 representative use passive mode, 0 representative not 
													//use passive mode, default is -1, represent use global mode


            public void Init ()
            {
                ftpTransferType = HttpFtp_FtpTransferType.FTT_NO_SET;
                iFtpUsePassiveMode = -1;
            }
        };

	}
}
