/// <summary>
        /// Gets some requests to be send to a peer. The requests will not exceed <see cref="Distribox.CommonLib.Properties.MaxRequestSize"/>
        /// </summary>
        /// <returns>
        /// The requests.
        /// </returns>
        public Tuple<List<FileEvent>, Peer> GetRequests()
        {
            CheckForRequestExpire();
            lock (this)
            {
                // No requests
                if (this.todoFileToPeer.Count() == 0)
                {
                    return null;
                }

                Peer bestPeer = new Peer();
                List<FileEvent> bestCollection = new List<FileEvent>();
                double bestScore = 0;
                long bestSize = 0;

                // For each peer
                foreach (KeyValuePair<Peer, List<FileEvent>> ppf in this.todoPeerToFile)
                {
                    Peer peer = ppf.Key;
                    var slist = ppf.Value.OrderBy(x => x.When.Ticks).ToList();

                    // Find file collections
                    double score = Properties.RMBandwidthWeight * this.estimator.GetPeerBandwidth(peer);

                    long currentSize = 0;
                    List<FileEvent> currentCollection = new List<FileEvent>();
                    foreach (FileEvent f in slist)
                    {
                        if (currentSize + f.Size <= Properties.MaxRequestSize)
                        {
                            currentSize += f.Size;
                            currentCollection.Add(f);

                            double uniqueness = 1.0 / this.todoFileToPeer[f].Count();
                            score += Properties.RMUniquenessWeight * uniqueness;
                        }
                        else
                        {
                            break;
                        }
                    }
                    score += Properties.RMSizeWeight * currentSize;

                    // Update best solution
                    if (score > bestScore)
                    {
                        bestScore = score;
                        bestPeer = peer;
                        bestCollection = currentCollection;
                        bestSize = currentSize;
                    }
                }

                // Do we have enough bandwidth ?
                int needBandwidth = this.estimator.GetPeerBandwidth(bestPeer);
                if (needBandwidth == 0)
                {
                    needBandwidth = Properties.DefaultConnectionSpeed;
                }

                if (usedBandwidth + needBandwidth > Properties.DefaultBandwidth)
                {
                    return null;
                }

                // Do this!
                Console.WriteLine("Request");
                usedBandwidth += needBandwidth;

                DoingQueueItem dqItem = new DoingQueueItem();
                dqItem.bandWidth = needBandwidth;
                dqItem.expireDate = DateTime.Now.AddSeconds(bestSize * Properties.ExpireSlackCoefficient / needBandwidth + Properties.DefaultDelay);
                dqItem.files = new List<DoingQueueFileItem>();

                foreach (FileEvent file in bestCollection)
                {
                    DoingQueueFileItem fileItem = new DoingQueueFileItem();
                    fileItem.file = file;
                    fileItem.whoHaveMe = this.todoFileToPeer[file];

                    // Remove File->Peer
                    this.todoFileToPeer.Remove(file);

                    // Remove Peer->File
                    foreach (Peer peer in fileItem.whoHaveMe)
                    {
                        this.todoPeerToFile[peer].Remove(file);
                    }

                    dqItem.files.Add(fileItem);
                }

                // Add it
                dqItem.filesHash = CommonHelper.GetHashCode(bestCollection);
                this.doing.Add(dqItem);
                this.estimator.BeginRequest(bestPeer, dqItem.filesHash, (int)bestSize);

                // return success
                return new Tuple<List<FileEvent>,Peer>(bestCollection, bestPeer);
            }
        }
        /// <summary>
        /// Gets some requests to be send to a peer. The requests will not exceed <see cref="Distribox.CommonLib.Properties.MaxRequestSize"/>
        /// </summary>
        /// <returns>
        /// The requests.
        /// </returns>
        public Tuple <List <FileEvent>, Peer> GetRequests()
        {
            CheckForRequestExpire();
            lock (this)
            {
                // No requests
                if (this.todoFileToPeer.Count() == 0)
                {
                    return(null);
                }

                Peer             bestPeer       = new Peer();
                List <FileEvent> bestCollection = new List <FileEvent>();
                double           bestScore      = 0;
                long             bestSize       = 0;

                // For each peer
                foreach (KeyValuePair <Peer, List <FileEvent> > ppf in this.todoPeerToFile)
                {
                    Peer peer  = ppf.Key;
                    var  slist = ppf.Value.OrderBy(x => x.When.Ticks).ToList();

                    // Find file collections
                    double score = Properties.RMBandwidthWeight * this.estimator.GetPeerBandwidth(peer);

                    long             currentSize       = 0;
                    List <FileEvent> currentCollection = new List <FileEvent>();
                    foreach (FileEvent f in slist)
                    {
                        if (currentSize + f.Size <= Properties.MaxRequestSize)
                        {
                            currentSize += f.Size;
                            currentCollection.Add(f);

                            double uniqueness = 1.0 / this.todoFileToPeer[f].Count();
                            score += Properties.RMUniquenessWeight * uniqueness;
                        }
                        else
                        {
                            break;
                        }
                    }
                    score += Properties.RMSizeWeight * currentSize;

                    // Update best solution
                    if (score > bestScore)
                    {
                        bestScore      = score;
                        bestPeer       = peer;
                        bestCollection = currentCollection;
                        bestSize       = currentSize;
                    }
                }

                // Do we have enough bandwidth ?
                int needBandwidth = this.estimator.GetPeerBandwidth(bestPeer);
                if (needBandwidth == 0)
                {
                    needBandwidth = Properties.DefaultConnectionSpeed;
                }

                if (usedBandwidth + needBandwidth > Properties.DefaultBandwidth)
                {
                    return(null);
                }

                // Do this!
                Console.WriteLine("Request");
                usedBandwidth += needBandwidth;

                DoingQueueItem dqItem = new DoingQueueItem();
                dqItem.bandWidth  = needBandwidth;
                dqItem.expireDate = DateTime.Now.AddSeconds(bestSize * Properties.ExpireSlackCoefficient / needBandwidth + Properties.DefaultDelay);
                dqItem.files      = new List <DoingQueueFileItem>();

                foreach (FileEvent file in bestCollection)
                {
                    DoingQueueFileItem fileItem = new DoingQueueFileItem();
                    fileItem.file      = file;
                    fileItem.whoHaveMe = this.todoFileToPeer[file];

                    // Remove File->Peer
                    this.todoFileToPeer.Remove(file);

                    // Remove Peer->File
                    foreach (Peer peer in fileItem.whoHaveMe)
                    {
                        this.todoPeerToFile[peer].Remove(file);
                    }

                    dqItem.files.Add(fileItem);
                }

                // Add it
                dqItem.filesHash = CommonHelper.GetHashCode(bestCollection);
                this.doing.Add(dqItem);
                this.estimator.BeginRequest(bestPeer, dqItem.filesHash, (int)bestSize);

                // return success
                return(new Tuple <List <FileEvent>, Peer>(bestCollection, bestPeer));
            }
        }