/// <summary>
 /// 获取初始化要下载的文件列表
 /// </summary>
 private void GetDownloadFileList()
 {
     downloadList.Clear();
     totalDownloadSize           = 0;
     alreadyDownloadSize         = 0;
     alreadyDownloadSuccessCount = 0;
     alreadyDownloadErrorCount   = 0;
     foreach (KeyValuePair <string, UpdateFileInfo> updateFileInfo in newFileInfoTable)
     {
         UpdateFileInfo fileInfo = null;
         oldFileInfoTable.TryGetValue(updateFileInfo.Key, out fileInfo);
         if (fileInfo?.Md5Code == updateFileInfo.Value.Md5Code)
         {
             continue;
         }
         downloadList.Add(updateFileInfo.Key);
         totalDownloadSize += updateFileInfo.Value.ZipLength;
     }
     if (downloadList.Count == 0)
     {
         //更新结束
         isUpdateDone = true;
         updateSucces();
         return;
     }
 }
        /// <summary>
        /// 检查本地客户端文件是否丢失
        /// </summary>
        /// <returns></returns>
        private bool CheckClientCorruption()
        {
            List <string> lostFiles = new List <string>();

            foreach (KeyValuePair <string, UpdateFileInfo> keyValuePair in oldFileInfoTable)
            {
                UpdateFileInfo fileInfo = keyValuePair.Value;
                string         filename =
                    PathUtility.GetCombinePath(AppConst.Path.PresistentDataPath, fileInfo.AssetBundleName);
                if (FileUtility.IsFileExist(filename))
                {
                    continue;
                }
                lostFiles.Add(fileInfo.AssetBundleName);
            }
            foreach (var file in lostFiles)
            {
                oldFileInfoTable.Remove(file);
            }
            if (lostFiles.Count > 0)
            {
                return(true);
            }
            return(false);
        }
        private void LoadHasUpdateFileList()
        {
            string filePath = PathUtility.GetCombinePath(AppConst.Path.PresistentDataPath,
                                                         AppConst.AssetBundleConfig.HasUpdateFileName);

            if (FileUtility.IsFileExist(filePath))
            {
                using (StreamReader sr = File.OpenText(filePath))
                {
                    string line;
                    while ((line = sr.ReadLine()) != null)
                    {
                        string[]       pair     = line.Split(',');
                        UpdateFileInfo fileInfo = new UpdateFileInfo
                        {
                            AssetBundleName = pair[0],
                            Length          = int.Parse(pair[1]),
                            Md5Code         = int.Parse(pair[2]),
                            ZipLength       = int.Parse(pair[3]),
                            ZipMd5Code      = int.Parse(pair[4])
                        };

                        if (oldFileInfoTable.ContainsKey(fileInfo.AssetBundleName))
                        {
                            oldFileInfoTable[fileInfo.AssetBundleName] = fileInfo;
                        }
                        else
                        {
                            oldFileInfoTable.Add(fileInfo.AssetBundleName, fileInfo);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// 获取沙河目录下面的文件列表信息
        /// </summary>
        /// <exception cref="Exception"></exception>
        private void LoadPresistentFilelist()
        {
            oldFileInfoTable.Clear();
            string filePath = PathUtility.GetCombinePath(AppConst.Path.PresistentDataPath,
                                                         AppConst.AssetBundleConfig.FileListFile);

            byte[] bytes = FileUtility.ReadAllBytes(filePath);
            if (bytes == null || bytes.Length == 0)
            {
                isUpdateDone = true;
                updateError("获取当前客户端的文件列表信息失败");
                return;
            }

            using (ByteBuffer buffer = new ByteBuffer(bytes))
            {
                fileCount = ValueParse.ReadValue(buffer, ValueParse.IntParse);
                for (int i = 0; i < fileCount; i++)
                {
                    UpdateFileInfo updateFileInfo = new UpdateFileInfo
                    {
                        AssetBundleName = ValueParse.ReadValue(buffer, ValueParse.StringParse),
                        Length          = ValueParse.ReadValue(buffer, ValueParse.IntParse),
                        Md5Code         = ValueParse.ReadValue(buffer, ValueParse.IntParse),
                        ZipLength       = ValueParse.ReadValue(buffer, ValueParse.IntParse),
                        ZipMd5Code      = ValueParse.ReadValue(buffer, ValueParse.IntParse)
                    };
                    oldFileInfoTable.Add(updateFileInfo.AssetBundleName, updateFileInfo);
                }
            }
        }
        private void DownloadErrorCallbcak(DownloadTask downloadTask, string message)
        {
            alreadyDownloadErrorCount++;
            UpdateFileInfo updateFileInfo = newFileInfoTable[downloadTask.FileName];

            downloadErrorList.Add(updateFileInfo.AssetBundleName);
            RefreshDownloadState();
        }
        private void DownloadDoneCallbcak(DownloadTask downloadTask, ulong size)
        {
            UpdateFileInfo updateFileInfo = newFileInfoTable[downloadTask.FileName];

            lock (lockObj)
            {
                if (VerificationFile(updateFileInfo, downloadTask.DownloadPath))
                {
                    alreadyDownloadSuccessCount++;
                    AppendHasUpdateFile(updateFileInfo);
                    RefreshDownloadState();
                }
                else
                {
                    DownloadErrorCallbcak(downloadTask, String.Empty);
                }
            }
        }
        public void AppendHasUpdateFile(UpdateFileInfo updateFileInfo)
        {
            string filePath = PathUtility.GetCombinePath(AppConst.Path.PresistentDataPath,
                                                         AppConst.AssetBundleConfig.HasUpdateFileName);

            try
            {
                using (FileStream fileStream = new FileStream(filePath, FileMode.Append))
                {
                    using (var write = new StreamWriter(fileStream))
                    {
                        write.WriteLine(updateFileInfo.AssetBundleName + "," + updateFileInfo.Length + "," +
                                        updateFileInfo.Md5Code + "," + updateFileInfo.ZipLength + "," +
                                        updateFileInfo.ZipMd5Code);
                    }
                }
            }
            catch (Exception e)
            {
                UnityEngine.Debug.LogError(e);
            }
        }
        private bool VerificationFile(UpdateFileInfo updateFileInfo, string filePath)
        {
//            return true;
            var length = 0;

            using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite))
            {
                length = (int)fileStream.Length;
                if (length != updateFileInfo.ZipLength)
                {
                    FileUtility.DeleteFile(filePath);
                    return(false);
                }
                if (updateFileCache == null || updateFileCache.Length < length)
                {
                    updateFileCache = new byte[(length / OneMegaBytes + 1) * OneMegaBytes];
                }
                int offset = 0;
                int count  = length;
                while (count > 0)
                {
                    int bytesRead = fileStream.Read(updateFileCache, offset, count);
                    offset += bytesRead;
                    count  -= bytesRead;
                }
            }

            if (serverBundleIsZip)
            {
                byte[] zipMd5Bytes = MD5Utility.GetMd5Bytes(updateFileCache, 0, length);
                int    zipMd5Code  = BitConverter.ToInt32(zipMd5Bytes, 0);
                if (zipMd5Code != updateFileInfo.ZipMd5Code)
                {
                    FileUtility.DeleteFile(filePath);
                    return(false);
                }
                int decompressSize = ZipUtility.DeCompressionFileInSamePath(filePath, serverBundleZipPassword);
                if (decompressSize != updateFileInfo.Length)
                {
                    FileUtility.DeleteFile(filePath);
                    return(false);
                }
            }
            else
            {
                byte[] md5Bytes = MD5Utility.GetMd5Bytes(updateFileCache, 0, length);
                int    md5Code  = BitConverter.ToInt32(md5Bytes, 0);
                if (md5Code != updateFileInfo.Md5Code)
                {
                    FileUtility.DeleteFile(filePath);
                    return(false);
                }
            }
            string srcPath = PathUtility.GetCombinePath(AppConst.Path.HotUpdateDownloadDataPath,
                                                        updateFileInfo.AssetBundleName);
            string desPath = PathUtility.GetCombinePath(AppConst.Path.PresistentDataPath,
                                                        updateFileInfo.AssetBundleName);

            if (FileUtility.IsFileExist(desPath))
            {
                FileUtility.DeleteFile(desPath);
            }
            FileUtility.Move(srcPath, desPath);
            if (FileUtility.IsFileExist(filePath))
            {
                FileUtility.DeleteFile(filePath);
            }
            return(true);
        }
        /// <summary>
        /// 加载server上的filelist callback
        /// </summary>
        /// <param name="isOk"></param>
        /// <param name="datas"></param>
        /// <param name="errorMessage"></param>
        private void LoadServerFileListCallback(bool isOk, byte[] datas, string errorMessage)
        {
            newFileInfoTable.Clear();
            if (isOk && datas != null && datas.Length > 0)
            {
                using (ByteBuffer buffer = new ByteBuffer(datas))
                {
                    fileCount = ValueParse.ReadValue(buffer, ValueParse.IntParse);
                    for (int i = 0; i < fileCount; i++)
                    {
                        UpdateFileInfo updateFileInfo = new UpdateFileInfo
                        {
                            AssetBundleName = ValueParse.ReadValue(buffer, ValueParse.StringParse),
                            Length          = ValueParse.ReadValue(buffer, ValueParse.IntParse),
                            Md5Code         = ValueParse.ReadValue(buffer, ValueParse.IntParse),
                            ZipLength       = ValueParse.ReadValue(buffer, ValueParse.IntParse),
                            ZipMd5Code      = ValueParse.ReadValue(buffer, ValueParse.IntParse)
                        };
                        newFileInfoTable.Add(updateFileInfo.AssetBundleName, updateFileInfo);
                    }
                }
                DeleteUselessFiles();
                GetDownloadFileList();
                if (!isUpdateDone)
                {
                    BeginDownFile();
                    return;

                    //检查磁盘空间是否满足大小 todo
                    if ((long)Math.Ceiling(totalDownloadSize * 1.1f) > MobileSystemInfo.GetFreeDiskSpace())
                    {
                        //磁盘空间不足
                    }
                    else
                    {
                        if (MobileSystemInfo.NetAvailable)
                        {
                            //运营商网络
                            if (MobileSystemInfo.IsCarrier)
                            {
                                updatePanel.ShowMessageBox(UpdatePanel.enMessageBoxType.CancelOk,
                                                           UpdateStringConfig.UpdateStatusBeginUpdate,
                                                           UpdateStringConfig.UpdateStringHasErrorNotWifi,
                                                           BeginDownFile, () =>
                                {
                                    if (Application.isPlaying)
                                    {
                                        Application.Quit();
                                    }
                                }, UpdateStringConfig.UpdateStatusWifiTips, FormatDownloadSize(totalDownloadSize));
                            }
                            // wi-fi 网络
                            else if (MobileSystemInfo.IsWifi)
                            {
                                //弹出提示框询问是否下载
                                updatePanel.ShowMessageBox(UpdatePanel.enMessageBoxType.CancelOk,
                                                           UpdateStringConfig.UpdateStatusBeginUpdate,
                                                           UpdateStringConfig.UpdateStateStartUpdateInfo,
                                                           BeginDownFile, () =>
                                {
                                    if (Application.isPlaying)
                                    {
                                        Application.Quit();
                                    }
                                }, UpdateStringConfig.UpdateStatusWifiTips, FormatDownloadSize(totalDownloadSize));
                            }
                        }
                    }
                }
            }
            else
            {
                //获取服务器的FileList失败
                isUpdateDone = true;
                updateError("获取服务器最新版本的文件列表信息失败");
            }
        }