private TLFile GetFile(TLInt dcId, TLInputVideoFileLocation location, TLInt offset, TLInt limit)
        {
            var    manualResetEvent = new ManualResetEvent(false);
            TLFile result           = null;

            _mtProtoService.GetFileAsync(dcId, location, offset, limit,
                                         file =>
            {
                result = file;
                manualResetEvent.Set();
            },
                                         error =>
            {
                int delay;
                lock (_randomRoot)
                {
                    delay = _random.Next(1000, 3000);
                }

                Execute.BeginOnThreadPool(TimeSpan.FromMilliseconds(delay), () => manualResetEvent.Set());
            });

            manualResetEvent.WaitOne();
            return(result);
        }
        private DownloadableItem GetDownloadableItem(TLInt dcId, TLInputVideoFileLocation location, TLObject owner, TLInt fileSize)
        {
            var item = new DownloadableItem
            {
                Owner = owner,
                DCId  = dcId,
                InputVideoLocation = location
            };

            item.Parts = GetItemParts(fileSize, item);

            return(item);
        }
        public void DownloadFileAsync(TLInt dcId, TLInputVideoFileLocation fileLocation, TLObject owner, TLInt fileSize, Action <double> callback)
        {
            Execute.BeginOnThreadPool(() =>
            {
                var downloadableItem = GetDownloadableItem(dcId, fileLocation, owner, fileSize);

                var downloadedCount = downloadableItem.Parts.Count(x => x.Status == PartStatus.Processed);
                var count           = downloadableItem.Parts.Count;
                var isComplete      = downloadedCount == count;

                if (isComplete)
                {
                    var id          = downloadableItem.InputVideoLocation.Id;
                    var accessHash  = downloadableItem.InputVideoLocation.AccessHash;
                    var fileName    = string.Format("video{0}_{1}.mp4", id, accessHash);
                    var getPartName = new Func <DownloadablePart, string>(x => string.Format("video{0}_{1}_{2}.dat", id, accessHash, x.Number));

                    FileUtils.MergePartsToFile(getPartName, downloadableItem.Parts, fileName);

                    downloadableItem.IsoFileName = fileName;
                    _eventAggregator.Publish(downloadableItem);
                }
                else
                {
                    var progress = downloadedCount / (double)count;
                    callback.SafeInvoke(progress);

                    lock (_itemsSyncRoot)
                    {
                        bool addFile = true;
                        foreach (var item in _items)
                        {
                            if (item.InputVideoLocation.AccessHash.Value == fileLocation.AccessHash.Value &&
                                item.InputVideoLocation.Id.Value == fileLocation.Id.Value &&
                                item.Owner == owner)
                            {
                                addFile = false;
                                break;
                            }
                        }

                        if (addFile)
                        {
                            _items.Add(downloadableItem);
                        }
                    }

                    StartAwaitingWorkers();
                }
            });
        }