using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;


namespace SiaSun.LMS.Common
{
    /// <summary>
    /// PDA设备操作类
    /// </summary>
    public class PDA_Device
    {
        RAPIInit inittrd = new RAPIInit();

        /// <summary>
        /// 连接PDA
        /// </summary>
        public string  ConnectPDA()
        {
            try
            {
                inittrd.RapiUnInit();
                inittrd.RapiInit();
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
            return null;
        }

        /// <summary>
        /// 断开连接
        /// </summary>
        public string DisConnectPDA()
        {
            try
            {
                int error = inittrd.RapiUnInit();
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
            return null;
        }

        /// <summary>
        /// 创建PDA文件
        /// </summary>
        public string DeletePDAFile(string PDA_FileName)
        {
            try
            {
                RAPI.CeDeleteFile(PDA_FileName);
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
            return null;
        }

        /// <summary>
        /// 从PDA拷贝文件到PC
        /// </summary>
        public string CopyFileFromPDA(string PC_FileName,string PDA_FileName)
        {
            try
            {
                ////判断文件是否存在
                //FileInfo flInfo = new FileInfo(PC_FileName);
                //if (flInfo.Exists)
                //{
                //    //删除现有文件
                //    flInfo.Delete();
                //}

                RAPI DownFilRapi = new RAPI(PC_FileName, PDA_FileName);
                DownFilRapi.RapiFileFromCE();
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
            return null;
        }

        /// <summary>
        /// 从PC拷贝文件到PDA
        /// </summary>
        public string CopyFileToPDA(string PC_FileName, string PDA_FileName)
        {
            try
            {
                RAPI DownFilRapi = new RAPI(PC_FileName, PDA_FileName);
                RAPI.CeDeleteFile(PDA_FileName);
                DownFilRapi.RapiFileToCE();
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
            return null;
        }

    }

    //连接CE设备
    public class RAPIInit
    {
        public int RapiInit()
        {
            int ret = CeRapiInit();

            if (ret != 0)
            {
                // 连接失败,获取失败代码
                ret = CeRapiGetError();

                // 抛出异常
                Marshal.ThrowExceptionForHR(ret);
            }
            return ret;
            // 连接成功
            // To Do
        }

        public int RapiUnInit()
        {
            return CeRapiUninit();
        }

        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        internal static extern int CeRapiGetError();

        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        internal static extern int CeRapiInit();

        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        internal static extern int CeRapiUninit();
    }

    //初始化RAPI
    public class RAPI
    {
        private const uint GENERIC_WRITE = 0x40000000;  // 设置读写权限
        private const uint GENERIC_READ = 0x80000000;  //设置读权限
        private const uint CREATE_ALWAYS = 2;    // 创建新文件
        private const short CREATE_NEWN = 1;    // 创建新文件
        private const short OPEN_EXISTING = 3;  //打开已有的文件
        private const short FILE_ATTRIBUTE_NORMAL = 0x80;  // 设置文件属性
        private const short INVALID_HANDLE_VALUE = -1;  // 错误句柄
        private String LocalFileName;
        private String RemoteFileName;

        IntPtr remoteFile = IntPtr.Zero;
        byte[] buffer = new byte[0x1000];    // 传输缓冲区定义为4k
        FileStream localFile;
        SafeFileHandle localFile1;

        int bytesread = 0;
        int byteswritten = 0;
        int filepos = 0;

        public RAPI(String LocalFileName, String RemoteFileName)
        {
            this.LocalFileName = LocalFileName;
            this.RemoteFileName = RemoteFileName;
        }

        //复制CE上的文件到PC机上
        public void RapiFileFromCE()
        {
            //打开CE系统上的文件
            remoteFile = CeCreateFile(RemoteFileName, GENERIC_READ, 0, 0, OPEN_EXISTING,
              FILE_ATTRIBUTE_NORMAL, 0);

            // 检查文件是否打开成功
            if ((int)remoteFile == INVALID_HANDLE_VALUE)
            {
                throw new Exception("Could not create remote file");
            }

            // 创建PC上的文件
            localFile1 = CreateFile(LocalFileName, GENERIC_WRITE, 0, IntPtr.Zero, CREATE_ALWAYS, 0, IntPtr.Zero);

            // 读取4K字节
            do
            {

                if (Convert.ToBoolean(CeReadFile(remoteFile, buffer, buffer.Length,
                           ref bytesread, 0)))
                {
                    // 写缓冲区数据到远程设备文件
                    if (!Convert.ToBoolean(WriteFile(localFile1, buffer, bytesread,
                     ref byteswritten, 0)))
                    { // 检查是否成功,不成功关闭文件句柄,抛出异常
                        CeCloseHandle(remoteFile);
                        throw new Exception("Could not write to remote file");
                    }
                }
            } while (Convert.ToBoolean(bytesread));
            localFile1.Close();
        }

        //PC上的文件写到CE上
        public void RapiFileToCE()
        {

            // 创建远程文件
            remoteFile = CeCreateFile(RemoteFileName, GENERIC_WRITE, 0, 0, CREATE_NEWN,
              FILE_ATTRIBUTE_NORMAL, 0);

            // 检查文件是否创建成功
            if ((int)remoteFile == INVALID_HANDLE_VALUE)
            {
                throw new Exception("Could not create remote file");
            }

            // 打开本地文件
            localFile = new FileStream(LocalFileName, FileMode.Open);

            // 读取4K字节
            bytesread = localFile.Read(buffer, filepos, buffer.Length);
            while (bytesread > 0)
            {
                // 移动文件指针到已读取的位置
                filepos += bytesread;

                // 写缓冲区数据到远程设备文件
                if (!Convert.ToBoolean(CeWriteFile(remoteFile, buffer, bytesread,
                 ref byteswritten, 0)))
                { // 检查是否成功,不成功关闭文件句柄,抛出异常
                    CeCloseHandle(remoteFile);
                    throw new Exception("Could not write to remote file");
                }
                try
                {
                    // 重新填充本地缓冲区
                    bytesread = localFile.Read(buffer, 0, buffer.Length);
                }
                catch (Exception)
                {
                    bytesread = 0;
                }
            }

            // 关闭本地文件
            localFile.Close();

            // 关闭远程文件
            CeCloseHandle(remoteFile);
        }


        // 声明要引用的API
        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        internal static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess,
          uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition,
          uint dwFlagsAndAttributes, IntPtr hTemplateFile);

        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        internal static extern Boolean WriteFile(SafeFileHandle lpFileName, byte[] lpBuffer,
         int nNumberOfbytesToWrite, ref int lpNumberOfbytesWritten, int lpOverlapped);

        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        internal static extern int CeCloseHandle(IntPtr hObject);

        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        internal static extern int CeCopyFile(
            string lpExistingFileName,
            string lpNewFileName,
            Boolean bFailIfExists);


        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        public static extern int CeDeleteFile(string DeviceFileName);




        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        internal static extern int CeWriteFile(IntPtr hFile, byte[] lpBuffer,
         int nNumberOfbytesToWrite, ref int lpNumberOfbytesWritten, int lpOverlapped);

        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        internal static extern int CeReadFile(IntPtr hFile, byte[] lpBuffer,
         int nNumberOfBytesToRead, ref int lpNumberOfBytesRead, int lpOverlapped);

        [DllImport("rapi.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        internal static extern IntPtr CeCreateFile(
         string lpFileName,
         uint dwDesiredAccess,
         int dwShareMode,
         int lpSecurityAttributes,
         int dwCreationDisposition,
         int dwFlagsAndAttributes,
         int hTemplateFile);
    }

}