public async Task DownloadBranch(DownloadBranchProperties properties, CancellationToken token = new CancellationToken())
        {
            var fd = new FileDownloader();

            if (properties.Languages == null)
            {
                properties.Languages = new List <string>()
                {
                    "en-us"
                }
            }
            ;

            if (_updateFiles == null)
            {
                for (var t = 1; t <= 20; t++)
                {
                    try
                    {
                        _updateFiles = await DownloadCabAsync();

                        break;
                    }
                    catch (Exception ex)
                    {
                    }
                    await Task.Delay(1000, token);
                }
            }

            var selectUpdateFile = new UpdateFiles();


            if (properties.OfficeEdition == OfficeEdition.Office32Bit)
            {
                selectUpdateFile = _updateFiles.FirstOrDefault(u => u.OfficeEdition == OfficeEdition.Office32Bit);
            }
            else if (properties.OfficeEdition == OfficeEdition.Office64Bit)
            {
                selectUpdateFile = _updateFiles.FirstOrDefault(u => u.OfficeEdition == OfficeEdition.Office64Bit);
            }
            else if (properties.OfficeEdition == OfficeEdition.Both)
            {
                var selectUpdateFile32 = _updateFiles.FirstOrDefault(u => u.OfficeEdition == OfficeEdition.Office32Bit);
                var selectUpdateFile64 = _updateFiles.FirstOrDefault(u => u.OfficeEdition == OfficeEdition.Office64Bit);

                selectUpdateFile32.Files.AddRange(selectUpdateFile64.Files);
                selectUpdateFile = selectUpdateFile32;
            }


            if (selectUpdateFile == null)
            {
                throw (new Exception("Cannot Find Office Files"));
            }

            var branch = selectUpdateFile.BaseURL.FirstOrDefault(b => b.Branch.ToLower() == properties.BranchName.ToLower());

            var version = properties.Version;

            if (string.IsNullOrEmpty(properties.Version))
            {
                version = await GetLatestVersionAsync(branch, properties.OfficeEdition);

                if (VersionDetected != null)
                {
                    VersionDetected(this, new Events.BuildVersion()
                    {
                        Version = version
                    });
                }
            }

            var allFiles = new List <Model.File>();

            foreach (var language in properties.Languages)
            {
                var langCode  = language.GetLanguageNumber();
                var langfiles = selectUpdateFile.Files.Where(f => f.Language == 0 || f.Language == langCode);

                foreach (var file in langfiles)
                {
                    file.Name         = Regex.Replace(file.Name, "%version%", version, RegexOptions.IgnoreCase);
                    file.RelativePath = Regex.Replace(file.RelativePath, "%version%", version, RegexOptions.IgnoreCase);
                    file.RemoteUrl    = branch.URL + @"/" + file.RelativePath + file.Name;
                    file.FileSize     = await fd.GetFileSizeAsync(file.RemoteUrl);

                    allFiles.Add(file);

                    if (token.IsCancellationRequested)
                    {
                        return;
                    }
                }
            }

            allFiles = allFiles.Distinct().ToList();

            fd = new FileDownloader();

            foreach (var file in allFiles)
            {
                file.LocalFilePath = properties.TargetDirectory + file.RelativePath.Replace("/", "\\") + file.Name;
            }

            double downloadedSize = 0;
            double totalSize      = allFiles.Where(f => !f.Exists).Sum(f => f.FileSize);

            foreach (var file in allFiles)
            {
                var localFilePath = properties.TargetDirectory + file.RelativePath.Replace("/", "\\") + file.Name;

                fd.DownloadFileProgress += (sender, progress) =>
                {
                    if (DownloadFileProgress == null)
                    {
                        return;
                    }
                    if (progress.PercentageComplete == 100.0)
                    {
                        return;
                    }

                    double bytesIn    = downloadedSize + progress.BytesRecieved;
                    double percentage = bytesIn / totalSize * 100;

                    if (percentage > 100)
                    {
                        percentage = 100;
                    }

                    DownloadFileProgress(this, new Events.DownloadFileProgress()
                    {
                        BytesRecieved       = (long)(downloadedSize + progress.BytesRecieved),
                        PercentageComplete  = Math.Truncate(percentage),
                        TotalBytesToRecieve = (long)totalSize
                    });
                };

                if (file.Exists)
                {
                    continue;
                }

                await fd.DownloadAsync(file.RemoteUrl, localFilePath, token);

                downloadedSize += file.FileSize;

                if (token.IsCancellationRequested)
                {
                    return;
                }
            }

            foreach (var file in allFiles)
            {
                var localFilePath = properties.TargetDirectory + file.RelativePath.Replace("/", "\\") + file.Name;

                if (string.IsNullOrEmpty(file.Rename))
                {
                    continue;
                }
                var fInfo = new FileInfo(localFilePath);
                File.Copy(localFilePath, fInfo.Directory.FullName + @"\" + file.Rename, true);
            }

            double percentageEnd = downloadedSize / totalSize * 100;

            if (percentageEnd == 99.0)
            {
                percentageEnd = 100;
            }

            if (DownloadFileProgress != null)
            {
                DownloadFileProgress(this, new Events.DownloadFileProgress()
                {
                    BytesRecieved       = (long)(downloadedSize),
                    PercentageComplete  = Math.Truncate(percentageEnd),
                    TotalBytesToRecieve = (long)totalSize
                });
            }

            if (DownloadFileComplete != null)
            {
                DownloadFileComplete(this, new Events.DownloadFileProgress()
                {
                    BytesRecieved       = (long)(downloadedSize),
                    PercentageComplete  = Math.Truncate(percentageEnd),
                    TotalBytesToRecieve = (long)totalSize
                });
            }
        }
        public async Task DownloadBranch(DownloadBranchProperties properties, CancellationToken token = new CancellationToken())
        {
            var fd = new FileDownloader();

            if (properties.Languages == null) properties.Languages = new List<string>() { "en-us" };

            if (_updateFiles == null)
            {
                for (var t = 1; t <= 20; t++)
                {
                    try
                    {
                        _updateFiles = await DownloadCabAsync();
                        break;
                    }
                    catch (Exception ex)
                    {
                       
                    }
                    await Task.Delay(1000, token);
                }
            }

            var selectUpdateFile = new UpdateFiles();


            if (properties.OfficeEdition == OfficeEdition.Office32Bit)
            {
                selectUpdateFile = _updateFiles.FirstOrDefault(u => u.OfficeEdition == OfficeEdition.Office32Bit);
            }
            else if (properties.OfficeEdition == OfficeEdition.Office64Bit)
            {
                selectUpdateFile = _updateFiles.FirstOrDefault(u => u.OfficeEdition == OfficeEdition.Office64Bit);
            }
            else if (properties.OfficeEdition == OfficeEdition.Both)
            {
                var selectUpdateFile32 = _updateFiles.FirstOrDefault(u => u.OfficeEdition == OfficeEdition.Office32Bit);
                var selectUpdateFile64 = _updateFiles.FirstOrDefault(u => u.OfficeEdition == OfficeEdition.Office64Bit);

                selectUpdateFile32.Files.AddRange(selectUpdateFile64.Files);
                selectUpdateFile = selectUpdateFile32;
            }


            if (selectUpdateFile == null) throw (new Exception("Cannot Find Office Files"));

            var branch = selectUpdateFile.BaseURL.FirstOrDefault(b => b.Branch.ToLower() == properties.BranchName.ToLower());

            var version = properties.Version;
            if (string.IsNullOrEmpty(properties.Version))
            {
                version = await GetLatestVersionAsync(branch, properties.OfficeEdition);
                if (VersionDetected != null)
                {
                    VersionDetected(this, new Events.BuildVersion()
                    {
                        Version = version
                    });
                }
            }

            var allFiles = new List<Model.File>();
            foreach (var language in properties.Languages)
            {
                var langCode = language.GetLanguageNumber();
                var langfiles = selectUpdateFile.Files.Where(f => f.Language == 0 || f.Language == langCode);

                foreach (var file in langfiles)
                {
                    file.Name = Regex.Replace(file.Name, "%version%", version, RegexOptions.IgnoreCase);
                    file.RelativePath = Regex.Replace(file.RelativePath, "%version%", version, RegexOptions.IgnoreCase);
                    file.RemoteUrl = branch.URL + @"/" + file.RelativePath + file.Name;
                    file.FileSize = await fd.GetFileSizeAsync(file.RemoteUrl);

                    allFiles.Add(file);

                    if (token.IsCancellationRequested)
                    {
                        return;
                    }
                }
            }

            allFiles = allFiles.Distinct().ToList();

            fd = new FileDownloader();

            foreach (var file in allFiles)
            {
                file.LocalFilePath = properties.TargetDirectory + file.RelativePath.Replace("/", "\\") + file.Name;
            }

            double downloadedSize = 0;
            double totalSize = allFiles.Where(f => !f.Exists).Sum(f => f.FileSize);

            foreach (var file in allFiles)
            {
                var localFilePath = properties.TargetDirectory + file.RelativePath.Replace("/", "\\") + file.Name;

                fd.DownloadFileProgress += (sender, progress) =>
                {
                    if (DownloadFileProgress == null) return;
                    if (progress.PercentageComplete == 100.0) return;

                    double bytesIn = downloadedSize + progress.BytesRecieved;
                    double percentage = bytesIn / totalSize * 100;

                    if (percentage > 100)
                    {
                        percentage = 100;
                    }

                    DownloadFileProgress(this, new Events.DownloadFileProgress()
                    {
                        BytesRecieved = (long)(downloadedSize + progress.BytesRecieved),
                        PercentageComplete = Math.Truncate(percentage),
                        TotalBytesToRecieve = (long)totalSize
                    });
                };

                if (file.Exists)
                {
                    continue;
                }

                await fd.DownloadAsync(file.RemoteUrl, localFilePath, token);
                downloadedSize += file.FileSize;

                if (token.IsCancellationRequested)
                {
                    return;
                }
            }

            foreach (var file in allFiles)
            {
                var localFilePath = properties.TargetDirectory + file.RelativePath.Replace("/", "\\") + file.Name;

                if (string.IsNullOrEmpty(file.Rename)) continue;
                var fInfo = new FileInfo(localFilePath);
                File.Copy(localFilePath, fInfo.Directory.FullName + @"\" + file.Rename, true);
            }

            double percentageEnd = downloadedSize / totalSize * 100;
            if (percentageEnd == 99.0) percentageEnd = 100;

            if (DownloadFileProgress != null)
            {
                DownloadFileProgress(this, new Events.DownloadFileProgress()
                {
                    BytesRecieved = (long) (downloadedSize),
                    PercentageComplete = Math.Truncate(percentageEnd),
                    TotalBytesToRecieve = (long) totalSize
                });
            }

            if (DownloadFileComplete != null)
            {
                DownloadFileComplete(this, new Events.DownloadFileProgress()
                {
                    BytesRecieved = (long) (downloadedSize),
                    PercentageComplete = Math.Truncate(percentageEnd),
                    TotalBytesToRecieve = (long) totalSize
                });
            }

        }
        public async Task <bool> ValidateSourceFiles(DownloadBranchProperties properties, CancellationToken token = new CancellationToken())
        {
            var fd = new FileDownloader();

            if (properties.Languages == null)
            {
                properties.Languages = new List <string>()
                {
                    "en-us"
                }
            }
            ;

            if (_updateFiles == null)
            {
                for (var t = 1; t <= 20; t++)
                {
                    try
                    {
                        _updateFiles = await DownloadCabAsync();

                        break;
                    }
                    catch (Exception ex)
                    {
                    }
                    await Task.Delay(1000, token);
                }
            }

            var selectUpdateFile = new UpdateFiles();


            if (properties.OfficeEdition == OfficeEdition.Office32Bit)
            {
                selectUpdateFile = _updateFiles.FirstOrDefault(u => u.OfficeEdition == OfficeEdition.Office32Bit);
            }
            else if (properties.OfficeEdition == OfficeEdition.Office64Bit)
            {
                selectUpdateFile = _updateFiles.FirstOrDefault(u => u.OfficeEdition == OfficeEdition.Office64Bit);
            }
            else if (properties.OfficeEdition == OfficeEdition.Both)
            {
                var selectUpdateFile32 = _updateFiles.FirstOrDefault(u => u.OfficeEdition == OfficeEdition.Office32Bit);
                var selectUpdateFile64 = _updateFiles.FirstOrDefault(u => u.OfficeEdition == OfficeEdition.Office64Bit);

                selectUpdateFile32.Files.AddRange(selectUpdateFile64.Files);
                selectUpdateFile = selectUpdateFile32;
            }


            if (selectUpdateFile == null)
            {
                throw (new Exception("Cannot Find Office Files"));
            }

            var branch = selectUpdateFile.BaseURL.FirstOrDefault(b => b.Branch.ToLower() == properties.BranchName.ToLower());

            var version = properties.Version;

            if (string.IsNullOrEmpty(properties.Version))
            {
                version = await GetLatestVersionAsync(branch, properties.OfficeEdition);
            }

            var allFiles = new List <Model.File>();

            foreach (var language in properties.Languages)
            {
                var langCode  = language.GetLanguageNumber();
                var langfiles = selectUpdateFile.Files.Where(f => f.Language == 0 || f.Language == langCode);

                foreach (var file in langfiles)
                {
                    file.Name         = Regex.Replace(file.Name, "%version%", version, RegexOptions.IgnoreCase);
                    file.RelativePath = Regex.Replace(file.RelativePath, "%version%", version, RegexOptions.IgnoreCase);
                    file.RemoteUrl    = branch.URL + @"/" + file.RelativePath + file.Name;
                    file.FileSize     = await fd.GetFileSizeAsync(file.RemoteUrl);

                    allFiles.Add(file);
                }
            }

            allFiles = allFiles.Distinct().ToList();

            foreach (var file in allFiles)
            {
                file.LocalFilePath = properties.TargetDirectory + file.RelativePath.Replace("/", "\\") + file.Name;
            }

            foreach (var file in allFiles)
            {
                var localFilePath = properties.TargetDirectory + file.RelativePath.Replace("/", "\\") + file.Name;
                if (!File.Exists(localFilePath))
                {
                    return(false);
                }
            }

            return(true);
        }
        public async Task<bool> ValidateSourceFiles(DownloadBranchProperties properties, CancellationToken token = new CancellationToken())
        {
            var fd = new FileDownloader();

            if (properties.Languages == null) properties.Languages = new List<string>() { "en-us" };

            if (_updateFiles == null)
            {
                for (var t = 1; t <= 20; t++)
                {
                    try
                    {
                        _updateFiles = await DownloadCabAsync();
                        break;
                    }
                    catch (Exception ex)
                    {

                    }
                    await Task.Delay(1000, token);
                }
            }

            var selectUpdateFile = new UpdateFiles();


            if (properties.OfficeEdition == OfficeEdition.Office32Bit)
            {
                selectUpdateFile = _updateFiles.FirstOrDefault(u => u.OfficeEdition == OfficeEdition.Office32Bit);
            }
            else if (properties.OfficeEdition == OfficeEdition.Office64Bit)
            {
                selectUpdateFile = _updateFiles.FirstOrDefault(u => u.OfficeEdition == OfficeEdition.Office64Bit);
            }
            else if (properties.OfficeEdition == OfficeEdition.Both)
            {
                var selectUpdateFile32 = _updateFiles.FirstOrDefault(u => u.OfficeEdition == OfficeEdition.Office32Bit);
                var selectUpdateFile64 = _updateFiles.FirstOrDefault(u => u.OfficeEdition == OfficeEdition.Office64Bit);

                selectUpdateFile32.Files.AddRange(selectUpdateFile64.Files);
                selectUpdateFile = selectUpdateFile32;
            }


            if (selectUpdateFile == null) throw (new Exception("Cannot Find Office Files"));

            var branch = selectUpdateFile.BaseURL.FirstOrDefault(b => b.Branch.ToLower() == properties.BranchName.ToLower());

            var version = properties.Version;
            if (string.IsNullOrEmpty(properties.Version))
            {
                version = await GetLatestVersionAsync(branch, properties.OfficeEdition);
            }

            var allFiles = new List<Model.File>();
            foreach (var language in properties.Languages)
            {
                var langCode = language.GetLanguageNumber();
                var langfiles = selectUpdateFile.Files.Where(f => f.Language == 0 || f.Language == langCode);

                foreach (var file in langfiles)
                {
                    file.Name = Regex.Replace(file.Name, "%version%", version, RegexOptions.IgnoreCase);
                    file.RelativePath = Regex.Replace(file.RelativePath, "%version%", version, RegexOptions.IgnoreCase);
                    file.RemoteUrl = branch.URL + @"/" + file.RelativePath + file.Name;
                    file.FileSize = await fd.GetFileSizeAsync(file.RemoteUrl);

                    allFiles.Add(file);
                }
            }

            allFiles = allFiles.Distinct().ToList();

            foreach (var file in allFiles)
            {
                file.LocalFilePath = properties.TargetDirectory + file.RelativePath.Replace("/", "\\") + file.Name;
            }

            foreach (var file in allFiles)
            {
                var localFilePath = properties.TargetDirectory + file.RelativePath.Replace("/", "\\") + file.Name;
                if (!File.Exists(localFilePath))
                {
                    return false;
                }
            }

            return true;
        }