public static async Task <bool> Upload(string[] logLines, GameMetaData gameMetaData, GameStats game)
        {
            var log  = string.Join(Environment.NewLine, logLines);
            var item = new UploaderItem(log.GetHashCode());

            if (InProgress.Contains(item))
            {
                Log.Info($"{item.Hash} already in progress. Waiting for it to complete...");
                InProgress.Add(item);
                return(await item.Success);
            }
            InProgress.Add(item);
            Log.Info($"Uploading {item.Hash}...");
            var success = false;

            try
            {
                success = await TryUpload(logLines, gameMetaData, game, true);
            }
            catch (Exception ex)
            {
                Log.Error(ex);
                Influx.OnGameUploadFailed();
            }
            Log.Info($"{item.Hash} complete. Success={success}");
            foreach (var waiting in InProgress.Where(x => x.Hash == item.Hash))
            {
                waiting.Complete(success);
            }
            InProgress.RemoveAll(x => x.Hash == item.Hash);
            return(success);
        }
        private static async Task <bool> TryUpload(string[] logLines, GameMetaData gameMetaData, GameStats game, bool submitFailure)
        {
            try
            {
                game?.HsReplay.UploadTry();
                Influx.OnGameUpload(game?.HsReplay.UploadTries ?? 1);
                var lines    = logLines.SkipWhile(x => !x.Contains("CREATE_GAME")).ToArray();
                var metaData = UploadMetaDataGenerator.Generate(lines, gameMetaData, game);
                Log.Info("Creating upload request...");
                var uploadRequest = await ApiWrapper.CreateUploadRequest(metaData);

                Log.Info("Upload Id: " + uploadRequest.ShortId);
                await ApiWrapper.UploadLog(uploadRequest, lines);

                Log.Info("Upload complete");
                if (game != null)
                {
                    game.HsReplay.UploadId  = uploadRequest.ShortId;
                    game.HsReplay.ReplayUrl = uploadRequest.ReplayUrl;
                    if (DefaultDeckStats.Instance.DeckStats.Any(x => x.DeckId == game.DeckId))
                    {
                        DefaultDeckStats.Save();
                    }
                    else
                    {
                        DeckStatsList.Save();
                    }
                }
                return(true);
            }
            catch (WebException ex)
            {
                Log.Error(ex);
                if (submitFailure)
                {
                    Influx.OnGameUploadFailed(ex.Status);
                }
                return(false);
            }
        }