﻿using Lucene.Net.Diagnostics;
using Lucene.Net.Index;
using Lucene.Net.Search;
using Lucene.Net.Util;
using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace Lucene.Net.Join
{
    /*
     * 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>
    /// Just like <see cref="ToParentBlockJoinQuery"/>, except this
    /// query joins in reverse: you provide a <see cref="Query"/> matching
    /// parent documents and it joins down to child
    /// documents.
    /// 
    /// @lucene.experimental
    /// </summary>
    public class ToChildBlockJoinQuery : Query
    {
        /// <summary>
        /// Message thrown from <see cref="ToChildBlockJoinScorer.ValidateParentDoc"/>
        /// on mis-use, when the parent query incorrectly returns child docs. 
        /// </summary>
        internal const string INVALID_QUERY_MESSAGE = "Parent query yields document which is not matched by parents filter, docID=";

        private readonly Filter _parentsFilter;
        private readonly Query _parentQuery;

        // If we are rewritten, this is the original parentQuery we
        // were passed; we use this for .equals() and
        // .hashCode().  This makes rewritten query equal the
        // original, so that user does not have to .rewrite() their
        // query before searching:
        private readonly Query _origParentQuery;
        private readonly bool _doScores;

        /// <summary>
        /// Create a <see cref="ToChildBlockJoinQuery"/>.
        /// </summary>
        /// <param name="parentQuery"><see cref="Query"/> that matches parent documents</param>
        /// <param name="parentsFilter"><see cref="Filter"/> (must produce FixedBitSet per-segment, like <see cref="FixedBitSetCachingWrapperFilter"/>) 
        /// identifying the parent documents.</param>
        /// <param name="doScores">True if parent scores should be calculated.</param>
        public ToChildBlockJoinQuery(Query parentQuery, Filter parentsFilter, bool doScores)
            : base()
        {
            _origParentQuery = parentQuery;
            _parentQuery = parentQuery;
            _parentsFilter = parentsFilter;
            _doScores = doScores;
        }

        private ToChildBlockJoinQuery(Query origParentQuery, Query parentQuery, Filter parentsFilter, bool doScores) 
            : base()
        {
            _origParentQuery = origParentQuery;
            _parentQuery = parentQuery;
            _parentsFilter = parentsFilter;
            _doScores = doScores;
        }
        
        public override Weight CreateWeight(IndexSearcher searcher)
        {
            return new ToChildBlockJoinWeight(this, _parentQuery.CreateWeight(searcher), _parentsFilter, _doScores);
        }

        private class ToChildBlockJoinWeight : Weight
        {
            private readonly Query _joinQuery;
            private readonly Weight _parentWeight;
            private readonly Filter _parentsFilter;
            private readonly bool _doScores;

            public ToChildBlockJoinWeight(Query joinQuery, Weight parentWeight, Filter parentsFilter, bool doScores) 
                : base()
            {
                _joinQuery = joinQuery;
                _parentWeight = parentWeight;
                _parentsFilter = parentsFilter;
                _doScores = doScores;
            }

            public override Query Query => _joinQuery;

            public override float GetValueForNormalization()
            {
                return _parentWeight.GetValueForNormalization() * _joinQuery.Boost*_joinQuery.Boost;
            }

            public override void Normalize(float norm, float topLevelBoost)
            {
                _parentWeight.Normalize(norm, topLevelBoost * _joinQuery.Boost);
            }

            // NOTE: acceptDocs applies (and is checked) only in the child document space
            public override Scorer GetScorer(AtomicReaderContext readerContext, IBits acceptDocs)
            {
                Scorer parentScorer = _parentWeight.GetScorer(readerContext, null);

                if (parentScorer == null)
                {
                    // No matches
                    return null;
                }

                // NOTE: we cannot pass acceptDocs here because this
                // will (most likely, justifiably) cause the filter to
                // not return a FixedBitSet but rather a
                // BitsFilteredDocIdSet.  Instead, we filter by
                // acceptDocs when we score:
                DocIdSet parents = _parentsFilter.GetDocIdSet(readerContext, null);

                if (parents == null)
                {
                    // No matches
                    return null;
                }
                if (!(parents is FixedBitSet))
                {
                    throw new InvalidOperationException("parentFilter must return FixedBitSet; got " + parents);
                }

                return new ToChildBlockJoinScorer(this, parentScorer, (FixedBitSet)parents, _doScores, acceptDocs);
            }
            
            public override Explanation Explain(AtomicReaderContext reader, int doc)
            {
                // TODO
                throw new NotSupportedException(GetType().Name + " cannot explain match on parent document");
            }

            public override bool ScoresDocsOutOfOrder => false;
        }

        private sealed class ToChildBlockJoinScorer : Scorer
        {
            private readonly Scorer _parentScorer;
            private readonly FixedBitSet _parentBits;
            private readonly bool _doScores;
            private readonly IBits _acceptDocs;

            private float _parentScore;
            private int _parentFreq = 1;

            private int _childDoc = -1;
            private int _parentDoc;

            public ToChildBlockJoinScorer(Weight weight, Scorer parentScorer, FixedBitSet parentBits, bool doScores, IBits acceptDocs) 
                : base(weight)
            {
                _doScores = doScores;
                _parentBits = parentBits;
                _parentScorer = parentScorer;
                _acceptDocs = acceptDocs;
            }

            public override ICollection<ChildScorer> GetChildren()
            {
                return new List<ChildScorer> { new ChildScorer(_parentScorer, "BLOCK_JOIN") };
            }
            
            public override int NextDoc()
            {
                //System.out.println("Q.nextDoc() parentDoc=" + parentDoc + " childDoc=" + childDoc);

                // Loop until we hit a childDoc that's accepted
                while (true)
                {
                    if (_childDoc + 1 == _parentDoc)
                    {
                        // OK, we are done iterating through all children
                        // matching this one parent doc, so we now nextDoc()
                        // the parent.  Use a while loop because we may have
                        // to skip over some number of parents w/ no
                        // children:
                        while (true)
                        {
                            _parentDoc = _parentScorer.NextDoc();
                            ValidateParentDoc();

                            if (_parentDoc == 0)
                            {
                                // Degenerate but allowed: first parent doc has no children
                                // TODO: would be nice to pull initial parent
                                // into ctor so we can skip this if... but it's
                                // tricky because scorer must return -1 for
                                // .doc() on init...
                                _parentDoc = _parentScorer.NextDoc();
                                ValidateParentDoc();
                            }

                            if (_parentDoc == NO_MORE_DOCS)
                            {
                                _childDoc = NO_MORE_DOCS;
                                //System.out.println("  END");
                                return _childDoc;
                            }

                            // Go to first child for this next parentDoc:
                            _childDoc = 1 + _parentBits.PrevSetBit(_parentDoc - 1);

                            if (_childDoc == _parentDoc)
                            {
                                // This parent has no children; continue
                                // parent loop so we move to next parent
                                continue;
                            }

                            if (_acceptDocs != null && !_acceptDocs.Get(_childDoc))
                            {
                                goto nextChildDocContinue;
                            }

                            if (_childDoc < _parentDoc)
                            {
                                if (_doScores)
                                {
                                    _parentScore = _parentScorer.GetScore();
                                    _parentFreq = _parentScorer.Freq;
                                }
                                //System.out.println("  " + childDoc);
                                return _childDoc;
                            }
                            else
                            {
                                // Degenerate but allowed: parent has no children
                            }
                        }
                    }

                    if (Debugging.AssertsEnabled) Debugging.Assert(_childDoc < _parentDoc, () => "childDoc=" + _childDoc + " parentDoc=" + _parentDoc);
                    _childDoc++;
                    if (_acceptDocs != null && !_acceptDocs.Get(_childDoc))
                    {
                        continue;
                    }
                    //System.out.println("  " + childDoc);
                    return _childDoc;
                    nextChildDocContinue:;
                }
            }

            /// <summary>
            /// Detect mis-use, where provided parent query in fact sometimes returns child documents.  
            /// </summary>
            private void ValidateParentDoc()
            {
                if (_parentDoc != NO_MORE_DOCS && !_parentBits.Get(_parentDoc))
                {
                    throw new InvalidOperationException(INVALID_QUERY_MESSAGE + _parentDoc);
                }
            }

            public override int DocID => _childDoc;

            public override float GetScore()
            {
                return _parentScore;
            }
            
            public override int Freq => _parentFreq;

            public override int Advance(int childTarget)
            {
                if (Debugging.AssertsEnabled) Debugging.Assert(childTarget >= _parentBits.Length || !_parentBits.Get(childTarget));

                //System.out.println("Q.advance childTarget=" + childTarget);
                if (childTarget == NO_MORE_DOCS)
                {
                    //System.out.println("  END");
                    return _childDoc = _parentDoc = NO_MORE_DOCS;
                }

                if (Debugging.AssertsEnabled) Debugging.Assert(_childDoc == -1 || childTarget != _parentDoc, () => "childTarget=" + childTarget);
                if (_childDoc == -1 || childTarget > _parentDoc)
                {
                    // Advance to new parent:
                    _parentDoc = _parentScorer.Advance(childTarget);
                    ValidateParentDoc();
                    //System.out.println("  advance to parentDoc=" + parentDoc);
                    if (Debugging.AssertsEnabled) Debugging.Assert(_parentDoc > childTarget);
                    if (_parentDoc == NO_MORE_DOCS)
                    {
                        //System.out.println("  END");
                        return _childDoc = NO_MORE_DOCS;
                    }
                    if (_doScores)
                    {
                        _parentScore = _parentScorer.GetScore();
                        _parentFreq = _parentScorer.Freq;
                    }
                    int firstChild = _parentBits.PrevSetBit(_parentDoc - 1);
                    //System.out.println("  firstChild=" + firstChild);
                    childTarget = Math.Max(childTarget, firstChild);
                }

                if (Debugging.AssertsEnabled) Debugging.Assert(childTarget < _parentDoc);

                // Advance within children of current parent:
                _childDoc = childTarget;
                //System.out.println("  " + childDoc);
                if (_acceptDocs != null && !_acceptDocs.Get(_childDoc))
                {
                    NextDoc();
                }
                return _childDoc;
            }

            public override long GetCost()
            {
                return _parentScorer.GetCost();
            }
        }

        public override void ExtractTerms(ISet<Term> terms)
        {
            _parentQuery.ExtractTerms(terms);
        }
        
        public override Query Rewrite(IndexReader reader)
        {
            Query parentRewrite = _parentQuery.Rewrite(reader);
            if (parentRewrite != _parentQuery)
            {
                Query rewritten = new ToChildBlockJoinQuery(_parentQuery, parentRewrite, _parentsFilter, _doScores);
                rewritten.Boost = Boost;
                return rewritten;
            }

            return this;
        }

        public override string ToString(string field)
        {
            return "ToChildBlockJoinQuery (" + _parentQuery + ")";
        }

        public override bool Equals(object obj)
        {
            if (obj is ToChildBlockJoinQuery)
            {
                ToChildBlockJoinQuery other = (ToChildBlockJoinQuery)obj;
                return _origParentQuery.Equals(other._origParentQuery) &&
                    _parentsFilter.Equals(other._parentsFilter) &&
                    _doScores == other._doScores &&
                    base.Equals(other);
            }
            else
            {
                return false;
            }
        }

        public override int GetHashCode()
        {
            unchecked
            {
                int hashCode = base.GetHashCode();
                hashCode = (hashCode*397) ^ (_origParentQuery != null ? _origParentQuery.GetHashCode() : 0);
                hashCode = (hashCode*397) ^ _doScores.GetHashCode();
                hashCode = (hashCode*397) ^ (_parentsFilter != null ? _parentsFilter.GetHashCode() : 0);
                return hashCode;
            }
        }

        public override object Clone()
        {
            return new ToChildBlockJoinQuery((Query) _origParentQuery.Clone(), _parentsFilter, _doScores);
        }
    }
}