public override void OnVerificationCompleted(PhoneAuthCredential credential)
 {
     Log.Debug("OnVerificationCompleted", "Worked");
     VerificationCompleted?.Invoke(this, new PhoneAuthCompletedEventArgs(credential));
 }
 public override void OnVerificationFailed(FirebaseException exception)
 {
     Log.Debug("OnVerificationFailed", exception.GetType().ToString());
     Log.Debug("OnVerificationFailed", exception.Class.ToString());
     VerificationCompleted?.Invoke(this, new PhoneAuthFailedEventArgs(exception));
 }
        public async Task DownloadAsync(string directory, Func <ManifestFile, bool> condition, CancellationToken cancellationToken = default)
        {
            if (IsRunning || _wasUsed)
            {
                throw new InvalidOperationException("Download task was already started or cannot be reused.");
            }

            try
            {
                IsRunning = true;
                _wasUsed  = true;

                // Create cancellation token source
                _cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _steamContentClient.CancellationToken);

                _serverPool = new SteamCdnServerPool(_steamContentClient, AppId, _cancellationTokenSource.Token);

                var chunks = new ConcurrentBag <ChunkJob>();

                // Filter out files that are directories or that the caller does not want
                var filteredFiles = Manifest.Files
                                    .Where(file => file.Flags != Enumerations.ManifestFileFlag.Directory && condition.Invoke(file))
                                    .OrderBy(x => x.FileName);

                // Verify all files in parallel
                var verificationTaskFactories = filteredFiles.Select(file => new Func <Task>(async() => await Task.Run(() => VerifyFileAsync(file, directory, chunks))));

                await ParallelAsync(
                    _steamContentClient.MaxConcurrentDownloadsPerTask,
                    new Queue <Func <Task> >(verificationTaskFactories),
                    (factory, task) => throw task.Exception,
                    _cancellationTokenSource.Token);

                if (VerificationCompleted != null)
                {
                    // Wait for all file verified eventhandlers to finish so we don't send events out of order
                    await WaitForEventHandlersAsync(_cancellationTokenSource.Token);

                    RunEventHandler(() => VerificationCompleted.Invoke(this, new VerificationCompletedArgs(chunks.Select(x => x.ManifestFile).Distinct().ToList())));
                }

                // Get the depot key with which we will process all chunks downloaded
                _depotKey = await _steamContentClient.GetDepotKeyAsync(DepotId, AppId);

                // Download all chunks in parallel
                var sortedChunks = chunks
                                   .GroupBy(x => x.ManifestFile.FileName)
                                   .OrderBy(x => x.Key)
                                   .SelectMany(x => x);

                var taskFactoriesQueue         = new Queue <Func <Task> >(sortedChunks.Select(chunkJob => new Func <Task>(async() => await Task.Run(() => DownloadChunkAsync(chunkJob, cancellationToken)))));
                var tasksFactoryFailuresLookup = new ConcurrentDictionary <Func <Task>, int>();

                await ParallelAsync(
                    _steamContentClient.MaxConcurrentDownloadsPerTask,
                    taskFactoriesQueue,
                    (factory, task) =>
                {
                    tasksFactoryFailuresLookup.AddOrUpdate(factory, 0, (key, existingVal) => existingVal + 1);

                    if (tasksFactoryFailuresLookup.GetValueOrDefault(factory, 0) >= 10)
                    {
                        throw new SteamDownloadException(task.Exception);
                    }

                    taskFactoriesQueue.Enqueue(factory);
                },
                    _cancellationTokenSource.Token);



                if (DownloadComplete != null)
                {
                    // Wait for all file verified eventhandlers to finish so we don't send events out of order
                    await WaitForEventHandlersAsync(_cancellationTokenSource.Token);

                    RunEventHandler(() => DownloadComplete.Invoke(this, new EventArgs()));
                }
            }
            catch (Exception ex)
            {
                throw;
            }
            finally
            {
                await Task.WhenAll(_fileWriters.Select(x => Task.Run(async() => await x.DisposeAsync().AsTask())));

                _serverPool?.Close();

                IsRunning = false;
            }
        }