using J2N.Threading.Atomic;
using Lucene.Net.Diagnostics;
using Lucene.Net.Documents;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;

namespace Lucene.Net.Index
{
    /*
     * Licensed to the Apache Software Foundation (ASF) under one or more
     * contributor license agreements.  See the NOTICE file distributed with
     * this work for additional information regarding copyright ownership.
     * The ASF licenses this file to You under the Apache License, Version 2.0
     * (the "License"); you may not use this file except in compliance with
     * the License.  You may obtain a copy of the License at
     *
     *     http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */

    using BinaryDocValuesField = BinaryDocValuesField;
    using BytesRef = Lucene.Net.Util.BytesRef;
    using Codec = Lucene.Net.Codecs.Codec;
    using Directory = Lucene.Net.Store.Directory;
    using DocValuesConsumer = Lucene.Net.Codecs.DocValuesConsumer;
    using DocValuesFormat = Lucene.Net.Codecs.DocValuesFormat;
    using IBits = Lucene.Net.Util.IBits;
    using IMutableBits = Lucene.Net.Util.IMutableBits;
    using IOContext = Lucene.Net.Store.IOContext;
    using IOUtils = Lucene.Net.Util.IOUtils;
    using LiveDocsFormat = Lucene.Net.Codecs.LiveDocsFormat;
    using NumericDocValuesField = NumericDocValuesField;
    using TrackingDirectoryWrapper = Lucene.Net.Store.TrackingDirectoryWrapper;

    /// <summary>
    /// Used by <see cref="IndexWriter"/> to hold open <see cref="SegmentReader"/>s (for
    /// searching or merging), plus pending deletes and updates,
    /// for a given segment
    /// </summary>
    internal class ReadersAndUpdates
    {
        // Not final because we replace (clone) when we need to
        // change it and it's been shared:
        public SegmentCommitInfo Info { get; private set; }

        // Tracks how many consumers are using this instance:
        private readonly AtomicInt32 refCount = new AtomicInt32(1);

        private readonly IndexWriter writer;

        // Set once (null, and then maybe set, and never set again):
        private SegmentReader reader;

        // TODO: it's sometimes wasteful that we hold open two
        // separate SRs (one for merging one for
        // reading)... maybe just use a single SR?  The gains of
        // not loading the terms index (for merging in the
        // non-NRT case) are far less now... and if the app has
        // any deletes it'll open real readers anyway.

        // Set once (null, and then maybe set, and never set again):
        private SegmentReader mergeReader;

        // Holds the current shared (readable and writable)
        // liveDocs.  this is null when there are no deleted
        // docs, and it's copy-on-write (cloned whenever we need
        // to change it but it's been shared to an external NRT
        // reader).
        private IBits liveDocs;

        // How many further deletions we've done against
        // liveDocs vs when we loaded it or last wrote it:
        private int pendingDeleteCount;

        // True if the current liveDocs is referenced by an
        // external NRT reader:
        private bool liveDocsShared;

        // Indicates whether this segment is currently being merged. While a segment
        // is merging, all field updates are also registered in the
        // mergingNumericUpdates map. Also, calls to writeFieldUpdates merge the
        // updates with mergingNumericUpdates.
        // That way, when the segment is done merging, IndexWriter can apply the
        // updates on the merged segment too.
        private bool isMerging = false;

        private readonly IDictionary<string, DocValuesFieldUpdates> mergingDVUpdates = new Dictionary<string, DocValuesFieldUpdates>();

        public ReadersAndUpdates(IndexWriter writer, SegmentCommitInfo info)
        {
            this.Info = info;
            this.writer = writer;
            liveDocsShared = true;
        }

        public virtual void IncRef()
        {
            int rc = refCount.IncrementAndGet();
            if (Debugging.AssertsEnabled) Debugging.Assert(rc > 1);
        }

        public virtual void DecRef()
        {
            int rc = refCount.DecrementAndGet();
            if (Debugging.AssertsEnabled) Debugging.Assert(rc >= 0);
        }

        public virtual int RefCount()
        {
            int rc = refCount;
            if (Debugging.AssertsEnabled) Debugging.Assert(rc >= 0);
            return rc;
        }

        public virtual int PendingDeleteCount
        {
            get
            {
                lock (this)
                {
                    return pendingDeleteCount;
                }
            }
        }

        // Call only from assert!
        public virtual bool VerifyDocCounts()
        {
            lock (this)
            {
                int count;
                if (liveDocs != null)
                {
                    count = 0;
                    for (int docID = 0; docID < Info.Info.DocCount; docID++)
                    {
                        if (liveDocs.Get(docID))
                        {
                            count++;
                        }
                    }
                }
                else
                {
                    count = Info.Info.DocCount;
                }

                if (Debugging.AssertsEnabled) Debugging.Assert(Info.Info.DocCount - Info.DelCount - pendingDeleteCount == count, "info.docCount={0} info.DelCount={1} pendingDeleteCount={2} count={3}", Info.Info.DocCount, Info.DelCount, pendingDeleteCount, count);
                return true;
            }
        }

        /// <summary>
        /// Returns a <see cref="SegmentReader"/>. </summary>
        public virtual SegmentReader GetReader(IOContext context)
        {
            if (reader == null)
            {
                // We steal returned ref:
                reader = new SegmentReader(Info, writer.Config.ReaderTermsIndexDivisor, context);
                if (liveDocs == null)
                {
                    liveDocs = reader.LiveDocs;
                }
            }

            // Ref for caller
            reader.IncRef();
            return reader;
        }

        // Get reader for merging (does not load the terms
        // index):
        public virtual SegmentReader GetMergeReader(IOContext context)
        {
            lock (this)
            {
                //System.out.println("  livedocs=" + rld.liveDocs);

                if (mergeReader == null)
                {
                    if (reader != null)
                    {
                        // Just use the already opened non-merge reader
                        // for merging.  In the NRT case this saves us
                        // pointless double-open:
                        //System.out.println("PROMOTE non-merge reader seg=" + rld.info);
                        // Ref for us:
                        reader.IncRef();
                        mergeReader = reader;
                        //System.out.println(Thread.currentThread().getName() + ": getMergeReader share seg=" + info.name);
                    }
                    else
                    {
                        //System.out.println(Thread.currentThread().getName() + ": getMergeReader seg=" + info.name);
                        // We steal returned ref:
                        mergeReader = new SegmentReader(Info, -1, context);
                        if (liveDocs == null)
                        {
                            liveDocs = mergeReader.LiveDocs;
                        }
                    }
                }

                // Ref for caller
                mergeReader.IncRef();
                return mergeReader;
            }
        }

        public virtual void Release(SegmentReader sr)
        {
            lock (this)
            {
                if (Debugging.AssertsEnabled) Debugging.Assert(Info == sr.SegmentInfo);
                sr.DecRef();
            }
        }

        public virtual bool Delete(int docID)
        {
            lock (this)
            {
                if (Debugging.AssertsEnabled)
                {
                    Debugging.Assert(liveDocs != null);
                    Debugging.Assert(Monitor.IsEntered(writer));
                    Debugging.Assert(docID >= 0 && docID < liveDocs.Length, "out of bounds: docid={0} liveDocsLength={1} seg={2} docCount={3}", docID, liveDocs.Length, Info.Info.Name, Info.Info.DocCount);
                    Debugging.Assert(!liveDocsShared);
                }
                bool didDelete = liveDocs.Get(docID);
                if (didDelete)
                {
                    ((IMutableBits)liveDocs).Clear(docID);
                    pendingDeleteCount++;
                    //System.out.println("  new del seg=" + info + " docID=" + docID + " pendingDelCount=" + pendingDeleteCount + " totDelCount=" + (info.docCount-liveDocs.count()));
                }
                return didDelete;
            }
        }

        // NOTE: removes callers ref
        public virtual void DropReaders()
        {
            lock (this)
            {
                // TODO: can we somehow use IOUtils here...?  problem is
                // we are calling .decRef not .close)...
                try
                {
                    if (reader != null)
                    {
                        //System.out.println("  pool.drop info=" + info + " rc=" + reader.getRefCount());
                        try
                        {
                            reader.DecRef();
                        }
                        finally
                        {
                            reader = null;
                        }
                    }
                }
                finally
                {
                    if (mergeReader != null)
                    {
                        //System.out.println("  pool.drop info=" + info + " merge rc=" + mergeReader.getRefCount());
                        try
                        {
                            mergeReader.DecRef();
                        }
                        finally
                        {
                            mergeReader = null;
                        }
                    }
                }

                DecRef();
            }
        }

        /// <summary>
        /// Returns a ref to a clone. NOTE: you should <see cref="DecRef()"/> the reader when you're
        /// done (ie do not call <see cref="IndexReader.Dispose()"/>).
        /// </summary>
        [MethodImpl(MethodImplOptions.NoInlining)]
        public virtual SegmentReader GetReadOnlyClone(IOContext context)
        {
            lock (this)
            {
                if (reader == null)
                {
                    GetReader(context).DecRef();
                    if (Debugging.AssertsEnabled) Debugging.Assert(reader != null);
                }
                liveDocsShared = true;
                if (liveDocs != null)
                {
                    return new SegmentReader(reader.SegmentInfo, reader, liveDocs, Info.Info.DocCount - Info.DelCount - pendingDeleteCount);
                }
                else
                {
                    if (Debugging.AssertsEnabled) Debugging.Assert(reader.LiveDocs == liveDocs);
                    reader.IncRef();
                    return reader;
                }
            }
        }

        public virtual void InitWritableLiveDocs()
        {
            lock (this)
            {
                if (Debugging.AssertsEnabled)
                {
                    Debugging.Assert(Monitor.IsEntered(writer));
                    Debugging.Assert(Info.Info.DocCount > 0);
                }
                //System.out.println("initWritableLivedocs seg=" + info + " liveDocs=" + liveDocs + " shared=" + shared);
                if (liveDocsShared)
                {
                    // Copy on write: this means we've cloned a
                    // SegmentReader sharing the current liveDocs
                    // instance; must now make a private clone so we can
                    // change it:
                    LiveDocsFormat liveDocsFormat = Info.Info.Codec.LiveDocsFormat;
                    if (liveDocs == null)
                    {
                        //System.out.println("create BV seg=" + info);
                        liveDocs = liveDocsFormat.NewLiveDocs(Info.Info.DocCount);
                    }
                    else
                    {
                        liveDocs = liveDocsFormat.NewLiveDocs(liveDocs);
                    }
                    liveDocsShared = false;
                }
            }
        }

        public virtual IBits LiveDocs
        {
            get
            {
                lock (this)
                {
                    if (Debugging.AssertsEnabled) Debugging.Assert(Monitor.IsEntered(writer));
                    return liveDocs;
                }
            }
        }

        public virtual IBits GetReadOnlyLiveDocs()
        {
            lock (this)
            {
                //System.out.println("getROLiveDocs seg=" + info);
                if (Debugging.AssertsEnabled) Debugging.Assert(Monitor.IsEntered(writer));
                liveDocsShared = true;
                //if (liveDocs != null) {
                //System.out.println("  liveCount=" + liveDocs.count());
                //}
                return liveDocs;
            }
        }

        public virtual void DropChanges()
        {
            lock (this)
            {
                // Discard (don't save) changes when we are dropping
                // the reader; this is used only on the sub-readers
                // after a successful merge.  If deletes had
                // accumulated on those sub-readers while the merge
                // is running, by now we have carried forward those
                // deletes onto the newly merged segment, so we can
                // discard them on the sub-readers:
                pendingDeleteCount = 0;
                DropMergingUpdates();
            }
        }

        // Commit live docs (writes new _X_N.del files) and field updates (writes new
        // _X_N updates files) to the directory; returns true if it wrote any file
        // and false if there were no new deletes or updates to write:
        // TODO (DVU_RENAME) to writeDeletesAndUpdates
        [MethodImpl(MethodImplOptions.NoInlining)]
        public virtual bool WriteLiveDocs(Directory dir)
        {
            lock (this)
            {
                if (Debugging.AssertsEnabled) Debugging.Assert(Monitor.IsEntered(writer));
                //System.out.println("rld.writeLiveDocs seg=" + info + " pendingDelCount=" + pendingDeleteCount + " numericUpdates=" + numericUpdates);
                if (pendingDeleteCount == 0)
                {
                    return false;
                }

                // We have new deletes
                if (Debugging.AssertsEnabled) Debugging.Assert(liveDocs.Length == Info.Info.DocCount);

                // Do this so we can delete any created files on
                // exception; this saves all codecs from having to do
                // it:
                TrackingDirectoryWrapper trackingDir = new TrackingDirectoryWrapper(dir);

                // We can write directly to the actual name (vs to a
                // .tmp & renaming it) because the file is not live
                // until segments file is written:
                bool success = false;
                try
                {
                    Codec codec = Info.Info.Codec;
                    codec.LiveDocsFormat.WriteLiveDocs((IMutableBits)liveDocs, trackingDir, Info, pendingDeleteCount, IOContext.DEFAULT);
                    success = true;
                }
                finally
                {
                    if (!success)
                    {
                        // Advance only the nextWriteDelGen so that a 2nd
                        // attempt to write will write to a new file
                        Info.AdvanceNextWriteDelGen();

                        // Delete any partially created file(s):
                        foreach (string fileName in trackingDir.CreatedFiles)
                        {
                            try
                            {
                                dir.DeleteFile(fileName);
                            }
                            catch (Exception)
                            {
                                // Ignore so we throw only the first exc
                            }
                        }
                    }
                }

                // If we hit an exc in the line above (eg disk full)
                // then info's delGen remains pointing to the previous
                // (successfully written) del docs:
                Info.AdvanceDelGen();
                Info.DelCount = Info.DelCount + pendingDeleteCount;
                pendingDeleteCount = 0;

                return true;
            }
        }

        // Writes field updates (new _X_N updates files) to the directory
        [MethodImpl(MethodImplOptions.NoInlining)]
        public virtual void WriteFieldUpdates(Directory dir, DocValuesFieldUpdates.Container dvUpdates)
        {
            lock (this)
            {
                if (Debugging.AssertsEnabled) Debugging.Assert(Monitor.IsEntered(writer));
                //System.out.println("rld.writeFieldUpdates: seg=" + info + " numericFieldUpdates=" + numericFieldUpdates);

                if (Debugging.AssertsEnabled) Debugging.Assert(dvUpdates.Any());

                // Do this so we can delete any created files on
                // exception; this saves all codecs from having to do
                // it:
                TrackingDirectoryWrapper trackingDir = new TrackingDirectoryWrapper(dir);

                FieldInfos fieldInfos = null;
                bool success = false;
                try
                {
                    Codec codec = Info.Info.Codec;

                    // reader could be null e.g. for a just merged segment (from
                    // IndexWriter.commitMergedDeletes).
                    SegmentReader reader = this.reader ?? new SegmentReader(Info, writer.Config.ReaderTermsIndexDivisor, IOContext.READ_ONCE);
                    try
                    {
                        // clone FieldInfos so that we can update their dvGen separately from
                        // the reader's infos and write them to a new fieldInfos_gen file
                        FieldInfos.Builder builder = new FieldInfos.Builder(writer.globalFieldNumberMap);
                        // cannot use builder.add(reader.getFieldInfos()) because it does not
                        // clone FI.attributes as well FI.dvGen
                        foreach (FieldInfo fi in reader.FieldInfos)
                        {
                            FieldInfo clone = builder.Add(fi);
                            // copy the stuff FieldInfos.Builder doesn't copy
                            if (fi.Attributes != null)
                            {
                                foreach (KeyValuePair<string, string> e in fi.Attributes)
                                {
                                    clone.PutAttribute(e.Key, e.Value);
                                }
                            }
                            clone.DocValuesGen = fi.DocValuesGen;
                        }
                        // create new fields or update existing ones to have NumericDV type
                        foreach (string f in dvUpdates.numericDVUpdates.Keys)
                        {
                            builder.AddOrUpdate(f, NumericDocValuesField.TYPE);
                        }
                        // create new fields or update existing ones to have BinaryDV type
                        foreach (string f in dvUpdates.binaryDVUpdates.Keys)
                        {
                            builder.AddOrUpdate(f, BinaryDocValuesField.fType);
                        }

                        fieldInfos = builder.Finish();
                        long nextFieldInfosGen = Info.NextFieldInfosGen;
                        string segmentSuffix = nextFieldInfosGen.ToString(CultureInfo.InvariantCulture);//Convert.ToString(nextFieldInfosGen, Character.MAX_RADIX));
                        SegmentWriteState state = new SegmentWriteState(null, trackingDir, Info.Info, fieldInfos, writer.Config.TermIndexInterval, null, IOContext.DEFAULT, segmentSuffix);
                        DocValuesFormat docValuesFormat = codec.DocValuesFormat;
                        DocValuesConsumer fieldsConsumer = docValuesFormat.FieldsConsumer(state);
                        bool fieldsConsumerSuccess = false;
                        try
                        {
                            //          System.out.println("[" + Thread.currentThread().getName() + "] RLD.writeFieldUpdates: applying numeric updates; seg=" + info + " updates=" + numericFieldUpdates);
                            foreach (KeyValuePair<string, NumericDocValuesFieldUpdates> e in dvUpdates.numericDVUpdates)
                            {
                                string field = e.Key;
                                NumericDocValuesFieldUpdates fieldUpdates = e.Value;
                                FieldInfo fieldInfo = fieldInfos.FieldInfo(field);
                                if (Debugging.AssertsEnabled) Debugging.Assert(fieldInfo != null);

                                fieldInfo.DocValuesGen = nextFieldInfosGen;
                                // write the numeric updates to a new gen'd docvalues file
                                fieldsConsumer.AddNumericField(fieldInfo, GetInt64Enumerable(reader, field, fieldUpdates));
                            }

                            //        System.out.println("[" + Thread.currentThread().getName() + "] RAU.writeFieldUpdates: applying binary updates; seg=" + info + " updates=" + dvUpdates.binaryDVUpdates);
                            foreach (KeyValuePair<string, BinaryDocValuesFieldUpdates> e in dvUpdates.binaryDVUpdates)
                            {
                                string field = e.Key;
                                BinaryDocValuesFieldUpdates dvFieldUpdates = e.Value;
                                FieldInfo fieldInfo = fieldInfos.FieldInfo(field);
                                if (Debugging.AssertsEnabled) Debugging.Assert(fieldInfo != null);

                                //          System.out.println("[" + Thread.currentThread().getName() + "] RAU.writeFieldUpdates: applying binary updates; seg=" + info + " f=" + dvFieldUpdates + ", updates=" + dvFieldUpdates);

                                fieldInfo.DocValuesGen = nextFieldInfosGen;
                                // write the numeric updates to a new gen'd docvalues file
                                fieldsConsumer.AddBinaryField(fieldInfo, GetBytesRefEnumerable(reader, field, dvFieldUpdates));
                            }

                            codec.FieldInfosFormat.FieldInfosWriter.Write(trackingDir, Info.Info.Name, segmentSuffix, fieldInfos, IOContext.DEFAULT);
                            fieldsConsumerSuccess = true;
                        }
                        finally
                        {
                            if (fieldsConsumerSuccess)
                            {
                                fieldsConsumer.Dispose();
                            }
                            else
                            {
                                IOUtils.DisposeWhileHandlingException(fieldsConsumer);
                            }
                        }
                    }
                    finally
                    {
                        if (reader != this.reader)
                        {
                            //          System.out.println("[" + Thread.currentThread().getName() + "] RLD.writeLiveDocs: closeReader " + reader);
                            reader.Dispose();
                        }
                    }

                    success = true;
                }
                finally
                {
                    if (!success)
                    {
                        // Advance only the nextWriteDocValuesGen so that a 2nd
                        // attempt to write will write to a new file
                        Info.AdvanceNextWriteFieldInfosGen();

                        // Delete any partially created file(s):
                        foreach (string fileName in trackingDir.CreatedFiles)
                        {
                            try
                            {
                                dir.DeleteFile(fileName);
                            }
                            catch (Exception)
                            {
                                // Ignore so we throw only the first exc
                            }
                        }
                    }
                }

                Info.AdvanceFieldInfosGen();
                // copy all the updates to mergingUpdates, so they can later be applied to the merged segment
                if (isMerging)
                {
                    foreach (KeyValuePair<string, NumericDocValuesFieldUpdates> e in dvUpdates.numericDVUpdates)
                    {
                        if (!mergingDVUpdates.TryGetValue(e.Key, out DocValuesFieldUpdates updates))
                        {
                            mergingDVUpdates[e.Key] = e.Value;
                        }
                        else
                        {
                            updates.Merge(e.Value);
                        }
                    }
                    foreach (KeyValuePair<string, BinaryDocValuesFieldUpdates> e in dvUpdates.binaryDVUpdates)
                    {
                        if (!mergingDVUpdates.TryGetValue(e.Key, out DocValuesFieldUpdates updates))
                        {
                            mergingDVUpdates[e.Key] = e.Value;
                        }
                        else
                        {
                            updates.Merge(e.Value);
                        }
                    }
                }

                // create a new map, keeping only the gens that are in use
                IDictionary<long, ISet<string>> genUpdatesFiles = Info.UpdatesFiles;
                IDictionary<long, ISet<string>> newGenUpdatesFiles = new Dictionary<long, ISet<string>>();
                long fieldInfosGen = Info.FieldInfosGen;
                foreach (FieldInfo fi in fieldInfos)
                {
                    long dvGen = fi.DocValuesGen;
                    if (dvGen != -1 && !newGenUpdatesFiles.ContainsKey(dvGen))
                    {
                        if (dvGen == fieldInfosGen)
                        {
                            newGenUpdatesFiles[fieldInfosGen] = trackingDir.CreatedFiles;
                        }
                        else
                        {
                            newGenUpdatesFiles[dvGen] = genUpdatesFiles[dvGen];
                        }
                    }
                }

                Info.SetGenUpdatesFiles(newGenUpdatesFiles);

                // wrote new files, should checkpoint()
                writer.Checkpoint();

                // if there is a reader open, reopen it to reflect the updates
                if (reader != null)
                {
                    SegmentReader newReader = new SegmentReader(Info, reader, liveDocs, Info.Info.DocCount - Info.DelCount - pendingDeleteCount);
                    bool reopened = false;
                    try
                    {
                        reader.DecRef();
                        reader = newReader;
                        reopened = true;
                    }
                    finally
                    {
                        if (!reopened)
                        {
                            newReader.DecRef();
                        }
                    }
                }
            }
        }

        /// <summary>
        /// NOTE: This was getLongEnumerable() in Lucene
        /// </summary>
        private IEnumerable<long?> GetInt64Enumerable(SegmentReader reader, string field, NumericDocValuesFieldUpdates fieldUpdates)
        {
            int maxDoc = reader.MaxDoc;
            IBits DocsWithField = reader.GetDocsWithField(field);
            NumericDocValues currentValues = reader.GetNumericDocValues(field);
            NumericDocValuesFieldUpdates.Iterator iter = (NumericDocValuesFieldUpdates.Iterator)fieldUpdates.GetIterator();
            int updateDoc = iter.NextDoc();

            for (int curDoc = 0; curDoc < maxDoc; ++curDoc)
            {
                if (curDoc == updateDoc) //document has an updated value
                {
                    long? value = (long?)iter.Value; // either null or updated
                    updateDoc = iter.NextDoc(); //prepare for next round
                    yield return value;
                }
                else
                {   // no update for this document
                    if (Debugging.AssertsEnabled) Debugging.Assert(curDoc < updateDoc);
                    if (currentValues != null && DocsWithField.Get(curDoc))
                    {
                        // only read the current value if the document had a value before
                        yield return currentValues.Get(curDoc);
                    }
                    else
                    {
                        yield return null;
                    }
                }
            }
        }

        private IEnumerable<BytesRef> GetBytesRefEnumerable(SegmentReader reader, string field, BinaryDocValuesFieldUpdates fieldUpdates)
        {
            BinaryDocValues currentValues = reader.GetBinaryDocValues(field);
            IBits DocsWithField = reader.GetDocsWithField(field);
            int maxDoc = reader.MaxDoc;
            var iter = (BinaryDocValuesFieldUpdates.Iterator)fieldUpdates.GetIterator();
            int updateDoc = iter.NextDoc();
            var scratch = new BytesRef();

            for (int curDoc = 0; curDoc < maxDoc; ++curDoc)
            {
                if (curDoc == updateDoc) //document has an updated value
                {
                    BytesRef value = (BytesRef)iter.Value; // either null or updated
                    updateDoc = iter.NextDoc(); //prepare for next round
                    yield return value;
                }
                else
                {   // no update for this document
                    if (Debugging.AssertsEnabled) Debugging.Assert(curDoc < updateDoc);
                    if (currentValues != null && DocsWithField.Get(curDoc))
                    {
                        // only read the current value if the document had a value before
                        currentValues.Get(curDoc, scratch);
                        yield return scratch;
                    }
                    else
                    {
                        yield return null;
                    }
                }
            }
        }

        /// <summary>
        /// Returns a reader for merge. this method applies field updates if there are
        /// any and marks that this segment is currently merging.
        /// </summary>
        internal virtual SegmentReader GetReaderForMerge(IOContext context)
        {
            lock (this)
            {
                if (Debugging.AssertsEnabled) Debugging.Assert(Monitor.IsEntered(writer));
                // must execute these two statements as atomic operation, otherwise we
                // could lose updates if e.g. another thread calls writeFieldUpdates in
                // between, or the updates are applied to the obtained reader, but then
                // re-applied in IW.commitMergedDeletes (unnecessary work and potential
                // bugs).
                isMerging = true;
                return GetReader(context);
            }
        }

        /// <summary>
        /// Drops all merging updates. Called from IndexWriter after this segment
        /// finished merging (whether successfully or not).
        /// </summary>
        public virtual void DropMergingUpdates()
        {
            lock (this)
            {
                mergingDVUpdates.Clear();
                isMerging = false;
            }
        }

        /// <summary>
        /// Returns updates that came in while this segment was merging. </summary>
        public virtual IDictionary<string, DocValuesFieldUpdates> MergingFieldUpdates
        {
            get
            {
                lock (this)
                {
                    return mergingDVUpdates;
                }
            }
        }

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("ReadersAndLiveDocs(seg=").Append(Info);
            sb.Append(" pendingDeleteCount=").Append(pendingDeleteCount);
            sb.Append(" liveDocsShared=").Append(liveDocsShared);
            return sb.ToString();
        }
    }
}