/// <summary>
        /// Creates n reviewsets distributing on documents
        /// </summary>
        /// <param name="reviewsetRecord"></param>
        private void SplitReviewsetOnNumberofDocs(DocumentRecordCollection reviewsetRecord)
        {
            reviewsetRecord.ShouldNotBe(null);
            reviewsetRecord.ReviewsetDetails.NumberOfDocumentsPerSet.ShouldBeGreaterThan(0);

            //find if there is any reminder document after calculated documents per set
            int remainderDocuments = m_TotalDocumentCount % reviewsetRecord.ReviewsetDetails.NumberOfDocumentsPerSet;

            //find the total number of reviewsets
            int totalReviewsets = Convert.ToInt32(m_TotalDocumentCount / reviewsetRecord.ReviewsetDetails.NumberOfDocumentsPerSet);

            //if there is any reminder document then increase the total reviewset count by 1
            totalReviewsets = remainderDocuments > 0 ? totalReviewsets + 1 : totalReviewsets;

            //get all the reviewset names
            List<ReviewsetDetails> reviewsetList = new List<ReviewsetDetails>();
            for (int i = 1; i <= totalReviewsets; i++)
            {
                int numberOfDocs = reviewsetRecord.ReviewsetDetails.NumberOfDocumentsPerSet;

                //if there are any remaining documents then add to last reviewset
                if (remainderDocuments > 0 && i == totalReviewsets)
                {
                    numberOfDocs = remainderDocuments;
                }

                reviewsetList.Add(new ReviewsetDetails
                {
                    ReviewsetName = (reviewsetRecord.ReviewsetDetails.Activity == Constants.SplitActivity) ?
                    (reviewsetRecord.ReviewsetDetails.ReviewSetName + (iSetStartNo + i)).ToString(CultureInfo.InvariantCulture) :
                    (reviewsetRecord.ReviewsetDetails.ReviewSetGroup + i).ToString(CultureInfo.InvariantCulture),
                    OriginalNoOfDocs = numberOfDocs
                });
            }

            SaveReviewsetMasterData(reviewsetList, reviewsetRecord);
        }
        /// <summary>
        /// creates reviewset with given details
        /// </summary>
        /// <param name="reviewsetRecord"></param>
        /// <returns></returns>
        private string CreateReviewset(DocumentRecordCollection reviewsetRecord)
        {
            reviewsetRecord.ShouldNotBe(null);
            string reviewsetName = reviewsetRecord.ReviewsetDetails.ReviewSetName;

            if (m_AllReviewSetinBinder.Exists(o => o.ReviewSetName.ToLower() == reviewsetName.ToLower()))
            {
                throw new Exception(string.Format("{0}{1}{2}", Constants.ReviewsetNameLog, reviewsetRecord.ReviewsetDetails.ReviewSetName, Constants.AlreadyExistsLog));
            }

            //create the review set with the details sent
            using (EVTransactionScope transScope = new EVTransactionScope(TransactionScopeOption.Suppress))
            {
                CreateReviewSetTaskBEO reviewSetBusinesssEntity = ConverttoReviewsetBusinessEntity(reviewsetRecord.ReviewsetDetails);
                //Creates the reviewset
                string reviewsetId = ReviewSetBO.CreateReviewSetJob(reviewSetBusinesssEntity);
                
                return reviewsetId;
            };
        }
        /// <summary>
        /// Splits the document based on number of review sets and creates the master data in DB
        /// </summary>
        /// <param name="reviewsetRecord"></param>
        private void SplitDocumentsOnNumberofReviewsets(DocumentRecordCollection reviewsetRecord)
        {
            reviewsetRecord.ShouldNotBe(null);
            reviewsetRecord.ReviewsetDetails.NumberOfReviewSets.ShouldBeGreaterThan(0);

            //temp holder for documents grouped
            List<DocumentGroupById> duplicateFamilyDocuments = new List<DocumentGroupById>();

            //holds review set names generated and number of documents to be assigned for each reviewset
            List<ReviewsetDetails> reviewsetList = new List<ReviewsetDetails>();

            //find if there is any reminder document after calculated documents per set
            int remainderDocuments = m_TotalDocumentCount % reviewsetRecord.ReviewsetDetails.NumberOfReviewSets;

            //find number of documents in a reviewset
            int docsPerReviewset = Convert.ToInt32(m_TotalDocumentCount / reviewsetRecord.ReviewsetDetails.NumberOfReviewSets);

            //get all the reviewset names and number of documents to be associated            
            for (int i = 1; i <= reviewsetRecord.ReviewsetDetails.NumberOfReviewSets; i++)
            {
                reviewsetList.Add(new ReviewsetDetails
                {
                    ReviewsetName = (reviewsetRecord.ReviewsetDetails.Activity == Constants.SplitActivity) ?
                    (reviewsetRecord.ReviewsetDetails.ReviewSetName + (iSetStartNo + i)).ToString(CultureInfo.InvariantCulture) :
                    (reviewsetRecord.ReviewsetDetails.ReviewSetGroup + i).ToString(CultureInfo.InvariantCulture),
                    OriginalNoOfDocs = docsPerReviewset
                });
            }

            //add the remaining documents equally in the reviewsets
            for (int i = 0; i < remainderDocuments; i++)
            {
                reviewsetList[i].OriginalNoOfDocs++;
            }

            //save the manipulated reviewset details in DB
            SaveReviewsetMasterData(reviewsetList, reviewsetRecord);
        }
        private void SendBatch(int size, string id, DocumentRecordCollection reviewsetRecord)
        {
            size.ShouldBeGreaterThan(0);
            id.ShouldNotBe(null);
            reviewsetRecord.ShouldNotBe(null);

            if (m_ReceivedDocuments.Count > 0)
            {
                //temporary list to hold the documents
                var tempList = new List<DocumentIdentityRecord>();

                //add the batch size to temporary list
                tempList.AddRange(m_ReceivedDocuments.GetRange(0, size));

                //remove all the associated documents from the received documents list
                var remainingList = m_ReceivedDocuments.Except(tempList).ToList();
                m_ReceivedDocuments.Clear();
                m_ReceivedDocuments.AddRange(remainingList);

                //assign the current filling review set id to all the documents in the temp list
                tempList.ForEach(x => x.ReviewsetId = id);

                //do not want to maintain this when there is no logic for Keep Families & Keep Duplicates
                if (m_KeepFamilies || m_KeepDuplicates)
                {
                    tempList.ForEach(
                        x =>
                            m_SentDocuments.Add(x.DocumentId,
                                new DocumentDetails { DuplicateID = x.DuplicateId, FamilyID = x.FamilyId }));
                }

                //clear the documents and add the temp list with all the details
                reviewsetRecord.Documents.Clear();
                reviewsetRecord.Documents.AddRange(tempList);

                //update the documents filled count for the review set
                m_AllReviewsets[id].FilledDocs += tempList.Count;

                Send(reviewsetRecord);


            }
        }
        /// <summary>
        /// splits into different batches to send to vault worker
        /// </summary>
        /// <param name="reviewsetRecord"></param>
        private void SendtoVaultWorker(DocumentRecordCollection reviewsetRecord)
        {
            reviewsetRecord.ShouldNotBe(null);
            int batchSize = m_BatchSize;

            //when the batch size is reached send to next worker
            if (m_ReceivedDocuments.Count >= batchSize)
            {
                //find the pending documents to update to reviewset
                int pendingDocsBeforeUpdate = m_AllReviewsets[reviewsetRecord.ReviewsetDetails.ReviewSetId].CalculatedNoOfDocs - m_AllReviewsets[reviewsetRecord.ReviewsetDetails.ReviewSetId].FilledDocs;
                int groupSize = batchSize;
                if (m_ReceivedDocuments.Count >= pendingDocsBeforeUpdate)
                {
                    groupSize = pendingDocsBeforeUpdate;
                }
                SendBatches(groupSize, reviewsetRecord.ReviewsetDetails.ReviewSetId, reviewsetRecord);
            }

            //find the pending documents to update to reviewset
            int pendingDocsAfterUpdate = m_AllReviewsets[reviewsetRecord.ReviewsetDetails.ReviewSetId].CalculatedNoOfDocs - m_AllReviewsets[reviewsetRecord.ReviewsetDetails.ReviewSetId].FilledDocs;

            //if there are any documents still pending
            if (m_ReceivedDocuments.Count > 0)
            {
                //if pending document is equal to excess document after batching then add all
                //the remaining documents and send as last instance to vault worker
                // or if the review set if filled with calculated number of documents even if it is less than batch count
                // still send the review set               
                if (m_ReceivedDocuments.Count.Equals(pendingDocsAfterUpdate) || pendingDocsAfterUpdate.Equals(m_AllReviewsets[reviewsetRecord.ReviewsetDetails.ReviewSetId].CalculatedNoOfDocs))
                {
                    SendBatches(((m_ReceivedDocuments.Count >= pendingDocsAfterUpdate) ? pendingDocsAfterUpdate : m_ReceivedDocuments.Count),
                        reviewsetRecord.ReviewsetDetails.ReviewSetId, reviewsetRecord);
                }
            }
        }
        /// <summary>
        /// Creates single reviewset and generates the reviewset id
        /// </summary>
        /// <param name="reviewsetRecord"></param>
        private void CreateSingleReviewset(DocumentRecordCollection reviewsetRecord)
        {
            reviewsetRecord.ShouldNotBe(null);

            //create reviewset in vault and get reviewset id
            if (String.IsNullOrWhiteSpace(m_LastUsedReviewSetId))
            {
                if (reviewsetRecord.ReviewsetDetails.Activity == Constants.SplitActivity)
                {
                    reviewsetRecord.ReviewsetDetails.ReviewSetName = string.Format("{0}{1}",
                        reviewsetRecord.ReviewsetDetails.ReviewSetName, (iSetStartNo + 1).ToString(CultureInfo.InvariantCulture));
                }
                m_LastUsedReviewSetId = CreateReviewset(reviewsetRecord);
            }
            //add review set details to the dictionary
            if (!m_AllReviewsets.ContainsKey(m_LastUsedReviewSetId) && (!string.IsNullOrEmpty(m_LastUsedReviewSetId)))
            {
                m_AllReviewsets.Add(m_LastUsedReviewSetId, new ReviewsetDetails { ReviewsetName = reviewsetRecord.ReviewsetDetails.ReviewSetName, CalculatedNoOfDocs = m_TotalDocumentCount });
            }
        }
        /// <summary>
        /// Tag the documents with not reviewed tag
        /// </summary>
        /// <param name="reviewsetRecord">Reviewset Record</param>
        /// <param name="tempList">List of documents added to reviewset</param>
        private void TagDocumentsNotReviewed(DocumentRecordCollection reviewsetRecord,
            List<ReviewsetDocumentBEO> tempList)
        {
            reviewsetRecord.ShouldNotBe(null);
            tempList.ShouldNotBe(null);
            var matterId = reviewsetRecord.ReviewsetDetails.MatterId.ToString(CultureInfo.InvariantCulture);
            var collectionId = reviewsetRecord.ReviewsetDetails.CollectionId;

            //var currentUser = EVSessionManager.Get<UserSessionBEO>(Constants.UserSessionInfo);
            var documentTagObjects = new List<DocumentTagBEO>();

            var _binderDetail = BinderVaultManagerInstance.GetBinderSpecificDetails(matterId,
                reviewsetRecord.ReviewsetDetails.BinderId);
            _binderDetail.ShouldNotBe(null);
            _binderDetail.NotReviewedTagId.ShouldBeGreaterThan(0);
            _binderDetail.ReviewedTagId.ShouldBeGreaterThan(0);
            reviewsetRecord.ReviewsetDetails.NotReviewedTagId = _binderDetail.NotReviewedTagId;
            reviewsetRecord.ReviewsetDetails.ReviewedTagId = _binderDetail.ReviewedTagId;


            var docsInfo = ConvertToBulkDocumentInfoBEO(tempList);

            //dictionary to hold list of documents to update
            var documentList = docsInfo.ToDictionary(a => a.DocumentId, a => a);

            //get Effective Tags for the give tag
            var effectiveTagList =
                BulkTagBO.GetEfectiveTags(matterId, new Guid(collectionId), _binderDetail.BinderId,
                    _binderDetail.NotReviewedTagId, Constants.One).ToList();

            var currentState = new List<DocumentTagBEO>();
            var newState = new List<DocumentTagBEO>();

            //get the list of tags with current status for the documents to be tagged
            currentState.AddRange(DocumentVaultManager.GetDocumentTags(matterId, new Guid(collectionId),
                documentList.Keys.ToList()));
            //for every tag from the effective list of tags to be updated
            foreach (var tag in effectiveTagList)
            {
                newState.AddRange(
                    documentList.Values.Select(
                        x =>
                            new DocumentTagBEO
                            {
                                TagId = tag.TagId,
                                Status = tag.TagState,
                                DocumentId = x.DocumentId,
                                DCN = x.DCN,
                                TagTypeSpecifier = tag.type,
                                TagName = tag.TagName
                            }));
            }

            //get all the documents that is not part of current documents list and update to vault
            var vaultChanges = newState.Except(currentState, new DocumentTagComparer()).Distinct().ToList();
            //Remove the entries that are already untagged but are marked for untagging
            vaultChanges.RemoveAll(document => document.Status == Constants.Untagged &&
                                               currentState.Exists(
                                                   y =>
                                                       y.TagId == document.TagId &&
                                                       String.Compare(y.DocumentId, document.DocumentId,
                                                           StringComparison.OrdinalIgnoreCase) == 0) == false);

            /* The following statement will take the untagged documents in the new state and 
             * make it as list of tagged documents so that except operator in the next statement 
             * remove all the tagged documents in the current state that have 
             * been untagged now.*/
            var newstateUntaggedDocuments = newState.Where(t => t.Status != Constants.Tagged).Select(t =>
                new DocumentTagBEO {TagId = t.TagId, DocumentId = t.DocumentId, Status = Constants.Tagged}).ToList();

            //Determine Tag changes to update in search index..This has to be supplied for IndexTaggerWorker to take care in search-engine
            var indexChanges = reviewsetRecord.DocumentTags = currentState.FindAll(currentStateOfDocument =>
                (newstateUntaggedDocuments.Find(newStateOfDocument =>
                    currentStateOfDocument.TagId == newStateOfDocument.TagId &&
                    currentStateOfDocument.DocumentId == newStateOfDocument.DocumentId
                    && currentStateOfDocument.Status == newStateOfDocument.Status) == null)).Union(newState).
                Distinct(new DocumentTagBEO()).ToList();

            DocumentVaultManager.UpdateDocumentTags(matterId, new Guid(collectionId), _binderDetail.BinderId,
                vaultChanges, indexChanges, _createdBy);
            Send(reviewsetRecord);
        }
        /// <summary>
        /// writes the list of documents into Vault
        /// </summary>
        /// <param name="reviewsetRecord"></param>
        private void WriteDocumentstoVault(DocumentRecordCollection reviewsetRecord)
        {
            reviewsetRecord.ShouldNotBe(null);
            var tempList = new List<ReviewsetDocumentBEO>();
            reviewsetRecord.ReviewsetDetails.CreatedBy.ShouldNotBeEmpty();
            reviewsetRecord.Documents.ShouldNotBe(null);
            _createdBy = reviewsetRecord.ReviewsetDetails.CreatedBy;
            _totalDocumentCount = reviewsetRecord.TotalDocumentCount;

            //stores converted document list
            tempList = ConvertDocumentRecordtoReviewsetDocument(reviewsetRecord.Documents,
                reviewsetRecord.ReviewsetDetails);

            if (EVHttpContext.CurrentContext == null)
            {
                // Moq the session
                MockSession();
            }

            ReviewSetBO.AddDocumentsToReviewSetForOverDrive(reviewsetRecord.ReviewsetDetails.MatterId.ToString(),
                reviewsetRecord.ReviewsetDetails.CollectionId, tempList);
        }