/// <summary>
        /// The on update validation ui.
        /// </summary>
        /// <param name="handler">
        /// The handler.
        /// </param>
        private void OnUpdateValidationUi(ZipFileValidationHandler handler)
        {
            var info = new DownloadProgressInfo(
                handler.TotalBytes, handler.CurrentBytes, handler.TimeRemaining, handler.AverageSpeed);

            this.RunOnUiThread(() => this.OnDownloadProgress(info));
        }
        /// <summary>
        /// Ensures that the zip file is valid.
        /// </summary>
        /// <param name="validationHandler">
        /// The class to hold the object for progress reporting
        /// </param>
        /// <returns>
        /// True if the zip is valid, otherwise False.
        /// </returns>
        public static bool Validate(ZipFileValidationHandler validationHandler)
        {
            var buf = new byte[1024 * 256];

            try
            {
                var            zip     = new ZipFile(validationHandler.Filename);
                ZipFileEntry[] entries = zip.GetAllEntries();

                // First calculate the total compressed length
                long  totalCompressedLength = entries.Sum(entry => entry.CompressedSize);
                float averageVerifySpeed    = 0;
                long  totalBytesRemaining   = totalCompressedLength;
                validationHandler.TotalBytes = totalCompressedLength;

                // Then calculate a CRC for every file in the Zip file,
                // comparing it to what is stored in the Zip directory
                foreach (ZipFileEntry entry in entries)
                {
                    if (entry.Crc32 != -1)
                    {
                        DateTime startTime = DateTime.UtcNow;

                        var crc = new Crc32();

                        uint offset = entry.FileOffset;
                        var  length = (int)entry.CompressedSize;

                        Stream raf = zip.zipFileStream;
                        raf.Seek(offset, SeekOrigin.Begin);

                        while (length > 0)
                        {
                            int seek = length > buf.Length ? buf.Length : length;
                            raf.Read(buf, 0, seek);
                            crc.Update(buf, 0, seek);
                            length -= seek;

                            DateTime currentTime = DateTime.UtcNow;
                            var      timePassed  = (float)(currentTime - startTime).TotalMilliseconds;
                            if (timePassed > 0)
                            {
                                float currentSpeedSample = seek / timePassed;
                                if (averageVerifySpeed <= 0)
                                {
                                    averageVerifySpeed = (SmoothingFactor * currentSpeedSample)
                                                         + ((1 - SmoothingFactor) * averageVerifySpeed);
                                }
                                else
                                {
                                    averageVerifySpeed = currentSpeedSample;
                                }

                                totalBytesRemaining -= seek;
                                var timeRemaining = (long)(totalBytesRemaining / averageVerifySpeed);

                                validationHandler.AverageSpeed  = averageVerifySpeed;
                                validationHandler.CurrentBytes  = totalCompressedLength - totalBytesRemaining;
                                validationHandler.TimeRemaining = timeRemaining;

                                validationHandler.UpdateUi(validationHandler);
                            }

                            startTime = currentTime;
                            if (validationHandler.ShouldCancel)
                            {
                                return(true);
                            }
                        }

                        if (crc.Value != entry.Crc32)
                        {
                            Debug.WriteLine("CRC does not match for entry: " + entry.FilenameInZip);
                            Debug.WriteLine("In file: " + entry.ZipFileName);

                            return(false);
                        }
                    }
                }
            }
            catch (IOException e)
            {
                Console.WriteLine(e.ToString());
                Console.Write(e.StackTrace);
                return(false);
            }

            return(true);
        }
        /// <summary>
        /// The is valid zip file.
        /// </summary>
        /// <param name="filename">
        /// The filename.
        /// </param>
        /// <returns>
        /// The is valid zip file.
        /// </returns>
        private bool IsValidZipFile(string filename)
        {
            this.zipFileValidationHandler = new ZipFileValidationHandler(filename)
                {
                   UpdateUi = this.OnUpdateValidationUi 
                };

            return File.Exists(filename) && ZipFile.Validate(this.zipFileValidationHandler);
        }
        /// <summary>
        /// Ensures that the zip file is valid.
        /// </summary>
        /// <param name="validationHandler">
        /// The class to hold the object for progress reporting
        /// </param>
        /// <returns>
        /// True if the zip is valid, otherwise False.
        /// </returns>
        public static bool Validate(ZipFileValidationHandler validationHandler)
        {
            var buf = new byte[1024 * 256];
            try
            {
                var zip = new ZipFile(validationHandler.Filename);
                ZipFileEntry[] entries = zip.GetAllEntries();

                // First calculate the total compressed length
                long totalCompressedLength = entries.Sum(entry => entry.CompressedSize);
                float averageVerifySpeed = 0;
                long totalBytesRemaining = totalCompressedLength;
                validationHandler.TotalBytes = totalCompressedLength;

                // Then calculate a CRC for every file in the Zip file,
                // comparing it to what is stored in the Zip directory
                foreach (ZipFileEntry entry in entries)
                {
                    if (entry.Crc32 != -1)
                    {
                        DateTime startTime = DateTime.UtcNow;

                        var crc = new Crc32();

                        uint offset = entry.FileOffset;
                        var length = (int)entry.CompressedSize;

                        Stream raf = zip.zipFileStream;
                        raf.Seek(offset, SeekOrigin.Begin);

                        while (length > 0)
                        {
                            int seek = length > buf.Length ? buf.Length : length;
                            raf.Read(buf, 0, seek);
                            crc.Update(buf, 0, seek);
                            length -= seek;

                            DateTime currentTime = DateTime.UtcNow;
                            var timePassed = (float)(currentTime - startTime).TotalMilliseconds;
                            if (timePassed > 0)
                            {
                                float currentSpeedSample = seek / timePassed;
                                if (averageVerifySpeed <= 0)
                                {
                                    averageVerifySpeed = (SmoothingFactor * currentSpeedSample)
                                                         + ((1 - SmoothingFactor) * averageVerifySpeed);
                                }
                                else
                                {
                                    averageVerifySpeed = currentSpeedSample;
                                }

                                totalBytesRemaining -= seek;
                                var timeRemaining = (long)(totalBytesRemaining / averageVerifySpeed);

                                validationHandler.AverageSpeed = averageVerifySpeed;
                                validationHandler.CurrentBytes = totalCompressedLength - totalBytesRemaining;
                                validationHandler.TimeRemaining = timeRemaining;

                                validationHandler.UpdateUi(validationHandler);
                            }

                            startTime = currentTime;
                            if (validationHandler.ShouldCancel)
                            {
                                return true;
                            }
                        }

                        if (crc.Value != entry.Crc32)
                        {
                            Debug.WriteLine("CRC does not match for entry: " + entry.FilenameInZip);
                            Debug.WriteLine("In file: " + entry.ZipFileName);

                            return false;
                        }
                    }
                }
            }
            catch (IOException e)
            {
                Console.WriteLine(e.ToString());
                Console.Write(e.StackTrace);
                return false;
            }

            return true;
        }