using J2N.Runtime.CompilerServices;
using Lucene.Net.Diagnostics;
using Lucene.Net.Index;
using Lucene.Net.Store;
using Lucene.Net.Support;
using Lucene.Net.Util;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using JCG = J2N.Collections.Generic;

namespace Lucene.Net.Codecs.Pulsing
{
    /*
     * 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.
     */

    /// <summary>
    /// Concrete class that reads the current doc/freq/skip postings format.
    /// <para/>
    /// @lucene.experimental
    /// </summary>
    // TODO: -- should we switch "hasProx" higher up?  and
    // create two separate docs readers, one that also reads
    // prox and one that doesn't?
    public class PulsingPostingsReader : PostingsReaderBase
    {
        // Fallback reader for non-pulsed terms:
        private readonly PostingsReaderBase _wrappedPostingsReader;
        private readonly SegmentReadState _segmentState;
        private int _maxPositions;
        private int _version;
        private IDictionary<int, int> _fields;

        public PulsingPostingsReader(SegmentReadState state, PostingsReaderBase wrappedPostingsReader)
        {
            _wrappedPostingsReader = wrappedPostingsReader;
            _segmentState = state;
        }

        public override void Init(IndexInput termsIn)
        {
            _version = CodecUtil.CheckHeader(termsIn, PulsingPostingsWriter.CODEC,
                PulsingPostingsWriter.VERSION_START,
                PulsingPostingsWriter.VERSION_CURRENT);

            _maxPositions = termsIn.ReadVInt32();
            _wrappedPostingsReader.Init(termsIn);

            if (_wrappedPostingsReader is PulsingPostingsReader || _version < PulsingPostingsWriter.VERSION_META_ARRAY)
            {
                _fields = null;
            }
            else
            {
                _fields = new JCG.SortedDictionary<int, int>();
                var summaryFileName = IndexFileNames.SegmentFileName(_segmentState.SegmentInfo.Name,
                    _segmentState.SegmentSuffix, PulsingPostingsWriter.SUMMARY_EXTENSION);
                IndexInput input = null;

                try
                {
                    input =
                        _segmentState.Directory.OpenInput(summaryFileName, _segmentState.Context);
                    CodecUtil.CheckHeader(input,
                        PulsingPostingsWriter.CODEC,
                        _version,
                        PulsingPostingsWriter.VERSION_CURRENT);

                    var numField = input.ReadVInt32();
                    for (var i = 0; i < numField; i++)
                    {
                        var fieldNum = input.ReadVInt32();
                        var longsSize = input.ReadVInt32();
                        _fields.Add(fieldNum, longsSize);
                    }
                }
                finally
                {
                    IOUtils.DisposeWhileHandlingException(input);
                }
            }
        }

        internal class PulsingTermState : BlockTermState
        {
            internal bool Absolute { get; set; }

            /// <summary>
            /// NOTE: This was longs (field) in Lucene
            /// </summary>
            [WritableArray]
            [SuppressMessage("Microsoft.Performance", "CA1819", Justification = "Lucene's design requires some writable array properties")]
            internal long[] Int64s { get; set; }
            [WritableArray]
            [SuppressMessage("Microsoft.Performance", "CA1819", Justification = "Lucene's design requires some writable array properties")]
            internal byte[] Postings { get; set; }
            internal int PostingsSize { get; set; } // -1 if this term was not inlined
            internal BlockTermState WrappedTermState { get; set; }

            public override object Clone()
            {
                var clone = (PulsingTermState)base.Clone();
                if (PostingsSize != -1)
                {
                    clone.Postings = new byte[PostingsSize];
                    Array.Copy(Postings, 0, clone.Postings, 0, PostingsSize);
                }
                else
                {
                    if (Debugging.AssertsEnabled) Debugging.Assert(WrappedTermState != null);
                    clone.WrappedTermState = (BlockTermState)WrappedTermState.Clone();
                    clone.Absolute = Absolute;

                    if (Int64s == null) return clone;

                    clone.Int64s = new long[Int64s.Length];
                    Array.Copy(Int64s, 0, clone.Int64s, 0, Int64s.Length);
                }
                return clone;
            }

            public override void CopyFrom(TermState other)
            {
                base.CopyFrom(other);
                var _other = (PulsingTermState)other;
                PostingsSize = _other.PostingsSize;
                if (_other.PostingsSize != -1)
                {
                    if (Postings == null || Postings.Length < _other.PostingsSize)
                    {
                        Postings = new byte[ArrayUtil.Oversize(_other.PostingsSize, 1)];
                    }
                    Array.Copy(_other.Postings, 0, Postings, 0, _other.PostingsSize);
                }
                else
                {
                    WrappedTermState.CopyFrom(_other.WrappedTermState);
                }
            }

            public override string ToString()
            {
                if (PostingsSize == -1)
                    return "PulsingTermState: not inlined: wrapped=" + WrappedTermState;

                return "PulsingTermState: inlined size=" + PostingsSize + " " + base.ToString();
            }
        }

        public override BlockTermState NewTermState()
        {
            return new PulsingTermState {WrappedTermState = _wrappedPostingsReader.NewTermState()};
        }

        public override void DecodeTerm(long[] empty, DataInput input, FieldInfo fieldInfo, BlockTermState termState,
            bool absolute)
        {
            var termState2 = (PulsingTermState) termState;

            if (Debugging.AssertsEnabled) Debugging.Assert(empty.Length == 0);

            termState2.Absolute = termState2.Absolute || absolute;
            // if we have positions, its total TF, otherwise its computed based on docFreq.
            // TODO Double check this is right..
            long count = fieldInfo.IndexOptions.CompareTo(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS) >= 0
                ? termState2.TotalTermFreq
                : termState2.DocFreq;
           
            if (count <= _maxPositions)
            {
                // Inlined into terms dict -- just read the byte[] blob in,
                // but don't decode it now (we only decode when a DocsEnum
                // or D&PEnum is pulled):
                termState2.PostingsSize = input.ReadVInt32();
                if (termState2.Postings == null || termState2.Postings.Length < termState2.PostingsSize)
                {
                    termState2.Postings = new byte[ArrayUtil.Oversize(termState2.PostingsSize, 1)];
                }
                // TODO: sort of silly to copy from one big byte[]
                // (the blob holding all inlined terms' blobs for
                // current term block) into another byte[] (just the
                // blob for this term)...
                input.ReadBytes(termState2.Postings, 0, termState2.PostingsSize);
                //System.out.println("  inlined bytes=" + termState.postingsSize);
                termState2.Absolute = termState2.Absolute || absolute;
            }
            else
            {
                //System.out.println("  not inlined");
                var longsSize = _fields == null ? 0 : _fields[fieldInfo.Number];
                if (termState2.Int64s == null)
                {
                    termState2.Int64s = new long[longsSize];
                }
                for (var i = 0; i < longsSize; i++)
                {
                    termState2.Int64s[i] = input.ReadVInt64();
                }
                termState2.PostingsSize = -1;
                termState2.WrappedTermState.DocFreq = termState2.DocFreq;
                termState2.WrappedTermState.TotalTermFreq = termState2.TotalTermFreq;
                _wrappedPostingsReader.DecodeTerm(termState2.Int64s, input, fieldInfo,
                    termState2.WrappedTermState,
                    termState2.Absolute);
                termState2.Absolute = false;
            }
        }

        public override DocsEnum Docs(FieldInfo field, BlockTermState termState, IBits liveDocs, DocsEnum reuse,
            DocsFlags flags)
        {
            var termState2 = (PulsingTermState) termState;
            if (termState2.PostingsSize != -1)
            {
                PulsingDocsEnum postings;
                if (reuse is PulsingDocsEnum)
                {
                    postings = (PulsingDocsEnum) reuse;
                    if (!postings.CanReuse(field))
                    {
                        postings = new PulsingDocsEnum(field);
                    }
                }
                else
                {
                    // the 'reuse' is actually the wrapped enum
                    var previous = (PulsingDocsEnum) GetOther(reuse);
                    if (previous != null && previous.CanReuse(field))
                    {
                        postings = previous;
                    }
                    else
                    {
                        postings = new PulsingDocsEnum(field);
                    }
                }
                
                if (reuse != postings)
                    SetOther(postings, reuse); // postings.other = reuse
                
                return postings.Reset(liveDocs, termState2);
            }

            if (!(reuse is PulsingDocsEnum))
                return _wrappedPostingsReader.Docs(field, termState2.WrappedTermState, liveDocs, reuse, flags);

            var wrapped = _wrappedPostingsReader.Docs(field, termState2.WrappedTermState, liveDocs,
                GetOther(reuse), flags);

            SetOther(wrapped, reuse); // wrapped.other = reuse
            return wrapped;
        }

        public override DocsAndPositionsEnum DocsAndPositions(FieldInfo field, BlockTermState termState, IBits liveDocs,
            DocsAndPositionsEnum reuse,
            DocsAndPositionsFlags flags)
        {

            var termState2 = (PulsingTermState) termState;

            if (termState2.PostingsSize != -1)
            {
                PulsingDocsAndPositionsEnum postings;
                if (reuse is PulsingDocsAndPositionsEnum)
                {
                    postings = (PulsingDocsAndPositionsEnum) reuse;
                    if (!postings.CanReuse(field))
                    {
                        postings = new PulsingDocsAndPositionsEnum(field);
                    }
                }
                else
                {
                    // the 'reuse' is actually the wrapped enum
                    var previous = (PulsingDocsAndPositionsEnum) GetOther(reuse);
                    if (previous != null && previous.CanReuse(field))
                    {
                        postings = previous;
                    }
                    else
                    {
                        postings = new PulsingDocsAndPositionsEnum(field);
                    }
                }
                if (reuse != postings)
                {
                    SetOther(postings, reuse); // postings.other = reuse 
                }
                return postings.Reset(liveDocs, termState2);
            }

            if (!(reuse is PulsingDocsAndPositionsEnum))
                return _wrappedPostingsReader.DocsAndPositions(field, termState2.WrappedTermState, liveDocs, reuse,
                    flags);

            var wrapped = _wrappedPostingsReader.DocsAndPositions(field,
                termState2.WrappedTermState,
                liveDocs, (DocsAndPositionsEnum) GetOther(reuse),
                flags);
            SetOther(wrapped, reuse); // wrapped.other = reuse
            return wrapped;
        }

        private class PulsingDocsEnum : DocsEnum
        {
            private byte[] _postingsBytes;
            private readonly ByteArrayDataInput _postings = new ByteArrayDataInput();
            private readonly IndexOptions _indexOptions;
            private readonly bool _storePayloads;
            private readonly bool _storeOffsets;
            private IBits _liveDocs;

            private int _docId = -1;
            private int _accum;
            private int _freq;
            private int _payloadLength;
            private int _cost;

            public PulsingDocsEnum(FieldInfo fieldInfo)
            {
                _indexOptions = fieldInfo.IndexOptions;
                _storePayloads = fieldInfo.HasPayloads;
                _storeOffsets = _indexOptions.CompareTo(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS) >= 0;
            }

            public virtual PulsingDocsEnum Reset(IBits liveDocs, PulsingTermState termState)
            {
                if (Debugging.AssertsEnabled) Debugging.Assert(termState.PostingsSize != -1);

                // Must make a copy of termState's byte[] so that if
                // app does TermsEnum.next(), this DocsEnum is not affected
                if (_postingsBytes == null)
                {
                    _postingsBytes = new byte[termState.PostingsSize];
                }
                else if (_postingsBytes.Length < termState.PostingsSize)
                {
                    _postingsBytes = ArrayUtil.Grow(_postingsBytes, termState.PostingsSize);
                }
                System.Array.Copy(termState.Postings, 0, _postingsBytes, 0, termState.PostingsSize);
                _postings.Reset(_postingsBytes, 0, termState.PostingsSize);
                _docId = -1;
                _accum = 0;
                _freq = 1;
                _cost = termState.DocFreq;
                _payloadLength = 0;
                this._liveDocs = liveDocs;
                return this;
            }

            internal bool CanReuse(FieldInfo fieldInfo)
            {
                return _indexOptions == fieldInfo.IndexOptions && _storePayloads == fieldInfo.HasPayloads;
            }

            public override int NextDoc()
            {
                while (true)
                {
                    if (_postings.Eof)
                        return _docId = NO_MORE_DOCS;

                    var code = _postings.ReadVInt32();
                    if (_indexOptions == IndexOptions.DOCS_ONLY)
                    {
                        _accum += code;
                    }
                    else
                    {
                        _accum += (int)((uint)code >> 1); ; // shift off low bit
                        _freq = (code & 1) != 0 ? 1 : _postings.ReadVInt32();

                        if (_indexOptions.CompareTo(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS) >= 0)
                        {
                            // Skip positions
                            if (_storePayloads)
                            {
                                for (var pos = 0; pos < _freq; pos++)
                                {
                                    var posCode = _postings.ReadVInt32();
                                    if ((posCode & 1) != 0)
                                    {
                                        _payloadLength = _postings.ReadVInt32();
                                    }
                                    if (_storeOffsets && (_postings.ReadVInt32() & 1) != 0)
                                    {
                                        // new offset length
                                        _postings.ReadVInt32();
                                    }
                                    if (_payloadLength != 0)
                                    {
                                        _postings.SkipBytes(_payloadLength);
                                    }
                                }
                            }
                            else
                            {
                                for (var pos = 0; pos < _freq; pos++)
                                {
                                    // TODO: skipVInt
                                    _postings.ReadVInt32();
                                    if (_storeOffsets && (_postings.ReadVInt32() & 1) != 0)
                                    {
                                        // new offset length
                                        _postings.ReadVInt32();
                                    }
                                }
                            }
                        }
                    }

                    if (_liveDocs == null || _liveDocs.Get(_accum))
                        return (_docId = _accum);
                }
            }

            public override int Freq => _freq;

            public override int DocID => _docId;

            public override int Advance(int target)
            {
                return _docId = SlowAdvance(target);
            }

            public override long GetCost()
            {
                return _cost;
            }
        }

        private class PulsingDocsAndPositionsEnum : DocsAndPositionsEnum
        {
            private byte[] _postingsBytes;
            private readonly ByteArrayDataInput _postings = new ByteArrayDataInput();
            private readonly bool _storePayloads;
            private readonly bool _storeOffsets;
            // note: we could actually reuse across different options, if we passed this to reset()
            // and re-init'ed storeOffsets accordingly (made it non-final)
            private readonly IndexOptions _indexOptions;

            private IBits _liveDocs;
            private int _docId = -1;
            private int _accum;
            private int _freq;
            private int _posPending;
            private int _position;
            private int _payloadLength;
            private BytesRef _payload;
            private int _startOffset;
            private int _offsetLength;

            private bool _payloadRetrieved;
            private int _cost;

            public PulsingDocsAndPositionsEnum(FieldInfo fieldInfo)
            {
                _indexOptions = fieldInfo.IndexOptions;
                _storePayloads = fieldInfo.HasPayloads;
                _storeOffsets = _indexOptions.CompareTo(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS) >= 0;
            }

            internal bool CanReuse(FieldInfo fieldInfo)
            {
                return _indexOptions == fieldInfo.IndexOptions && _storePayloads == fieldInfo.HasPayloads;
            }

            public virtual PulsingDocsAndPositionsEnum Reset(IBits liveDocs, PulsingTermState termState)
            {
                if (Debugging.AssertsEnabled) Debugging.Assert(termState.PostingsSize != -1);

                if (_postingsBytes == null)
                {
                    _postingsBytes = new byte[termState.PostingsSize];
                }
                else if (_postingsBytes.Length < termState.PostingsSize)
                {
                    _postingsBytes = ArrayUtil.Grow(_postingsBytes, termState.PostingsSize);
                }

                Array.Copy(termState.Postings, 0, _postingsBytes, 0, termState.PostingsSize);
                _postings.Reset(_postingsBytes, 0, termState.PostingsSize);
                this._liveDocs = liveDocs;
                _payloadLength = 0;
                _posPending = 0;
                _docId = -1;
                _accum = 0;
                _cost = termState.DocFreq;
                _startOffset = _storeOffsets ? 0 : -1; // always return -1 if no offsets are stored
                _offsetLength = 0;
                //System.out.println("PR d&p reset storesPayloads=" + storePayloads + " bytes=" + bytes.length + " this=" + this);
                return this;
            }

            public override int NextDoc()
            {
                while (true)
                {
                    SkipPositions();

                    if (_postings.Eof)
                    {
                        return _docId = NO_MORE_DOCS;
                    }

                    var code = _postings.ReadVInt32();
                    _accum += (int)((uint)code >> 1); // shift off low bit 
                    _freq = (code & 1) != 0 ? 1 : _postings.ReadVInt32();
                    _posPending = _freq;
                    _startOffset = _storeOffsets ? 0 : -1; // always return -1 if no offsets are stored

                    if (_liveDocs != null && !_liveDocs.Get(_accum)) continue;

                    _position = 0;
                    return (_docId = _accum);
                }
            }

            public override int Freq => _freq;

            public override int DocID => _docId;

            public override int Advance(int target)
            {
                return _docId = SlowAdvance(target);
            }

            public override int NextPosition()
            {
                if (Debugging.AssertsEnabled) Debugging.Assert(_posPending > 0);

                _posPending--;

                if (_storePayloads)
                {
                    if (!_payloadRetrieved)
                    {
                        _postings.SkipBytes(_payloadLength);
                    }
                    int code = _postings.ReadVInt32();
                    if ((code & 1) != 0)
                    {
                        _payloadLength = _postings.ReadVInt32();
                    }
                    _position += (int)((uint)code >> 1);
                    _payloadRetrieved = false;
                }
                else
                {
                    _position += _postings.ReadVInt32();
                }

                if (_storeOffsets)
                {
                    int offsetCode = _postings.ReadVInt32();
                    if ((offsetCode & 1) != 0)
                    {
                        // new offset length
                        _offsetLength = _postings.ReadVInt32();
                    }
                    _startOffset += (int)((uint)offsetCode >> 1);
                }

                return _position;
            }

            public override int StartOffset => _startOffset;

            public override int EndOffset => _startOffset + _offsetLength;

            private void SkipPositions()
            {
                while (_posPending != 0)
                {
                    NextPosition();
                }
                if (_storePayloads && !_payloadRetrieved)
                {
                    _postings.SkipBytes(_payloadLength);
                    _payloadRetrieved = true;
                }
            }

            public override BytesRef GetPayload()
            {
                if (_payloadRetrieved)
                    return _payload;

                if (_storePayloads && _payloadLength > 0)
                {
                    _payloadRetrieved = true;
                    if (_payload == null)
                    {
                        _payload = new BytesRef(_payloadLength);
                    }
                    else
                    {
                        _payload.Grow(_payloadLength);
                    }
                    _postings.ReadBytes(_payload.Bytes, 0, _payloadLength);
                    _payload.Length = _payloadLength;
                    return _payload;
                }

                return null;
            }

            public override long GetCost()
            {
                return _cost;
            }
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _wrappedPostingsReader.Dispose();
            }
        }

        /// <summary>
        /// For a docsenum, gets the 'other' reused enum.
        /// Example: Pulsing(Standard).
        /// When doing a term range query you are switching back and forth
        /// between Pulsing and Standard.
        /// <para/>
        /// The way the reuse works is that Pulsing.other = Standard and
        /// Standard.other = Pulsing.
        /// </summary>
        private DocsEnum GetOther(DocsEnum de)
        {
            if (de == null)
                return null;

            var atts = de.Attributes;
            DocsEnum result;
            atts.AddAttribute<IPulsingEnumAttribute>().Enums.TryGetValue(this, out result);
            return result;
        }

        /// <summary>
        /// For a docsenum, sets the 'other' reused enum.
        /// see <see cref="GetOther(DocsEnum)"/> for an example.
        /// </summary>
        private DocsEnum SetOther(DocsEnum de, DocsEnum other)
        {
            var atts = de.Attributes;
            return atts.AddAttribute<IPulsingEnumAttribute>().Enums[this] = other;
        }

        ///<summary>
        /// A per-docsenum attribute that stores additional reuse information
        /// so that pulsing enums can keep a reference to their wrapped enums,
        /// and vice versa. this way we can always reuse.
        /// <para/>
        /// @lucene.internal 
        /// </summary>
        public interface IPulsingEnumAttribute : IAttribute
        {
            IDictionary<PulsingPostingsReader, DocsEnum> Enums { get; }
        }

        /// <summary>
        /// Implementation of <see cref="PulsingEnumAttribute"/> for reuse of
        /// wrapped postings readers underneath pulsing.
        /// <para/>
        /// @lucene.internal
        /// </summary>
        public sealed class PulsingEnumAttribute : Util.Attribute, IPulsingEnumAttribute
        {
            // we could store 'other', but what if someone 'chained' multiple postings readers,
            // this could cause problems?
            // TODO: we should consider nuking this map and just making it so if you do this,
            // you don't reuse? and maybe pulsingPostingsReader should throw an exc if it wraps
            // another pulsing, because this is just stupid and wasteful. 
            // we still have to be careful in case someone does Pulsing(Stomping(Pulsing(...
            private readonly IDictionary<PulsingPostingsReader, DocsEnum> _enums = new JCG.Dictionary<PulsingPostingsReader, DocsEnum>(IdentityEqualityComparer<PulsingPostingsReader>.Default);

            public IDictionary<PulsingPostingsReader, DocsEnum> Enums => _enums;

            public override void Clear()
            {
                // our state is per-docsenum, so this makes no sense.
                // its best not to clear, in case a wrapped enum has a per-doc attribute or something
                // and is calling clearAttributes(), so they don't nuke the reuse information!
            }

            public override void CopyTo(Util.IAttribute target)
            {
                // this makes no sense for us, because our state is per-docsenum.
                // we don't want to copy any stuff over to another docsenum ever!
            }
        }

        public override long RamBytesUsed()
        {
            return ((_wrappedPostingsReader != null) ? _wrappedPostingsReader.RamBytesUsed() : 0);
        }

        public override void CheckIntegrity()
        {
            _wrappedPostingsReader.CheckIntegrity();
        }  
    }
}
