using J2N;
using J2N.Collections.Generic.Extensions;
using Lucene.Net.Util;
using System;
using System.Collections;
using System.Collections.Generic;

#if FEATURE_SERIALIZABLE_EXCEPTIONS
using System.ComponentModel;
using System.Runtime.Serialization;
#endif
using System.Text;
using JCG = J2N.Collections.Generic;

namespace Lucene.Net.Search
{
    /*
     * 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 AtomicReaderContext = Lucene.Net.Index.AtomicReaderContext;
    using IBits = Lucene.Net.Util.IBits;
    using IndexReader = Lucene.Net.Index.IndexReader;
    using Occur_e = Lucene.Net.Search.Occur;
    using Similarity = Lucene.Net.Search.Similarities.Similarity;
    using Term = Lucene.Net.Index.Term;
    using ToStringUtils = Lucene.Net.Util.ToStringUtils;

    /// <summary>
    /// A <see cref="Query"/> that matches documents matching boolean combinations of other
    /// queries, e.g. <see cref="TermQuery"/>s, <see cref="PhraseQuery"/>s or other
    /// <see cref="BooleanQuery"/>s.
    /// <para/>
    /// Collection initializer note: To create and populate a <see cref="BooleanQuery"/>
    /// in a single statement, you can use the following example as a guide:
    ///
    /// <code>
    /// var booleanQuery = new BooleanQuery() {
    ///     { new WildcardQuery(new Term("field2", "foobar")), Occur.SHOULD },
    ///     { new MultiPhraseQuery() {
    ///         new Term("field", "microsoft"),
    ///         new Term("field", "office")
    ///     }, Occur.SHOULD }
    /// };
    ///
    /// // or
    ///
    /// var booleanQuery = new BooleanQuery() {
    ///     new BooleanClause(new WildcardQuery(new Term("field2", "foobar")), Occur.SHOULD),
    ///     new BooleanClause(new MultiPhraseQuery() {
    ///         new Term("field", "microsoft"),
    ///         new Term("field", "office")
    ///     }, Occur.SHOULD)
    /// };
    /// </code>
    /// </summary>
    public class BooleanQuery : Query, IEnumerable<BooleanClause>
    {
        private static int maxClauseCount = 1024;

        /// <summary>
        /// Thrown when an attempt is made to add more than
        /// <see cref="MaxClauseCount"/> clauses. This typically happens if
        /// a <see cref="PrefixQuery"/>, <see cref="FuzzyQuery"/>, <see cref="WildcardQuery"/>, or <see cref="TermRangeQuery"/>
        /// is expanded to many terms during search.
        /// </summary>
        // LUCENENET: It is no longer good practice to use binary serialization.
        // See: https://github.com/dotnet/corefx/issues/23584#issuecomment-325724568
#if FEATURE_SERIALIZABLE_EXCEPTIONS
        [Serializable]
#endif
        // LUCENENET specific: Added IRuntimeException for identification of the Java superclass in .NET
        public class TooManyClausesException : Exception, IRuntimeException // LUCENENET specific - added Exception suffix
        {
            public TooManyClausesException()
                : base("maxClauseCount is set to " + maxClauseCount)
            {
            }

#if FEATURE_SERIALIZABLE_EXCEPTIONS
            /// <summary>
            /// Initializes a new instance of this class with serialized data.
            /// </summary>
            /// <param name="info">The <see cref="SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
            /// <param name="context">The <see cref="StreamingContext"/> that contains contextual information about the source or destination.</param>
            [Obsolete("This API supports obsolete formatter-based serialization. It should not be called or extended by application code.")]
            [EditorBrowsable(EditorBrowsableState.Never)]
            protected TooManyClausesException(SerializationInfo info, StreamingContext context)
                : base(info, context)
            {
            }
#endif
        }

        /// <summary>
        /// Return the maximum number of clauses permitted, 1024 by default.
        /// Attempts to add more than the permitted number of clauses cause
        /// <see cref="TooManyClausesException"/> to be thrown. </summary>
        public static int MaxClauseCount
        {
            get => maxClauseCount;
            set
            {
                if (value < 1)
                {
                    throw new ArgumentOutOfRangeException(nameof(MaxClauseCount), "maxClauseCount must be >= 1"); // LUCENENET specific - changed from IllegalArgumentException to ArgumentOutOfRangeException (.NET convention)
                }
                BooleanQuery.maxClauseCount = value;
            }
        }

        private IList<BooleanClause> clauses = new JCG.List<BooleanClause>();
        private readonly bool disableCoord;

        /// <summary>
        /// Constructs an empty boolean query. </summary>
        public BooleanQuery()
        {
            disableCoord = false;
        }

        /// <summary>
        /// Constructs an empty boolean query.
        /// <para/>
        /// <see cref="Similarity.Coord(int,int)"/> may be disabled in scoring, as
        /// appropriate. For example, this score factor does not make sense for most
        /// automatically generated queries, like <see cref="WildcardQuery"/> and
        /// <see cref="FuzzyQuery"/>.
        /// </summary>
        /// <param name="disableCoord"> Disables <see cref="Similarity.Coord(int,int)"/> in scoring. </param>
        public BooleanQuery(bool disableCoord)
        {
            this.disableCoord = disableCoord;
        }

        /// <summary>
        /// Returns true if <see cref="Similarity.Coord(int,int)"/> is disabled in
        /// scoring for this query instance. </summary>
        /// <seealso cref="BooleanQuery(bool)"/>
        public virtual bool CoordDisabled => disableCoord; // LUCENENET TODO: API Change to CoordEnabled? Per MSDN, properties should be in the affirmative.

        /// <summary>
        /// Specifies a minimum number of the optional <see cref="BooleanClause"/>s
        /// which must be satisfied.
        ///
        /// <para>
        /// By default no optional clauses are necessary for a match
        /// (unless there are no required clauses).  If this method is used,
        /// then the specified number of clauses is required.
        /// </para>
        /// <para>
        /// Use of this method is totally independent of specifying that
        /// any specific clauses are required (or prohibited).  This number will
        /// only be compared against the number of matching optional clauses.
        /// </para>
        /// </summary>
        /// <param name="value"> The number of optional clauses that must match </param>
        public virtual int MinimumNumberShouldMatch
        {
            get => m_minNrShouldMatch;
            set => this.m_minNrShouldMatch = value;
        }

        protected int m_minNrShouldMatch = 0;

        /// <summary>
        /// Adds a clause to a boolean query.
        /// </summary>
        /// <exception cref="TooManyClausesException"> If the new number of clauses exceeds the maximum clause number </exception>
        /// <seealso cref="MaxClauseCount"/>
        public virtual void Add(Query query, Occur occur)
        {
            Add(new BooleanClause(query, occur));
        }

        /// <summary>
        /// Adds a clause to a boolean query. </summary>
        /// <exception cref="TooManyClausesException"> If the new number of clauses exceeds the maximum clause number </exception>
        /// <seealso cref="MaxClauseCount"/>
        public virtual void Add(BooleanClause clause)
        {
            if (clauses.Count >= maxClauseCount)
            {
                throw new TooManyClausesException();
            }

            clauses.Add(clause);
        }

        /// <summary>
        /// Returns the set of clauses in this query. </summary>
        public virtual BooleanClause[] GetClauses()
        {
            return clauses.ToArray();
        }

        /// <summary>
        /// Returns the list of clauses in this query. </summary>
        public virtual IList<BooleanClause> Clauses => clauses;

        /// <summary>
        /// Returns an iterator on the clauses in this query. It implements the <see cref="T:IEnumerable{BooleanClause}"/> interface to
        /// make it possible to do:
        /// <code>foreach (BooleanClause clause in booleanQuery) {}</code>
        /// </summary>
        public IEnumerator<BooleanClause> GetEnumerator()
        {
            return Clauses.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        /// <summary>
        /// Expert: the <see cref="Weight"/> for <see cref="BooleanQuery"/>, used to
        /// normalize, score and explain these queries.
        /// <para/>
        /// @lucene.experimental
        /// </summary>
        public class BooleanWeight : Weight
        {
            private readonly BooleanQuery outerInstance;

            /// <summary>
            /// The <see cref="Similarities.Similarity"/> implementation. </summary>
            protected Similarity m_similarity;

            protected IList<Weight> m_weights;
            protected int m_maxCoord; // num optional + num required
            private readonly bool disableCoord;

            public BooleanWeight(BooleanQuery outerInstance, IndexSearcher searcher, bool disableCoord)
            {
                this.outerInstance = outerInstance;
                this.m_similarity = searcher.Similarity;
                this.disableCoord = disableCoord;
                m_weights = new JCG.List<Weight>(outerInstance.clauses.Count);
                for (int i = 0; i < outerInstance.clauses.Count; i++)
                {
                    BooleanClause c = outerInstance.clauses[i];
                    Weight w = c.Query.CreateWeight(searcher);
                    m_weights.Add(w);
                    if (!c.IsProhibited)
                    {
                        m_maxCoord++;
                    }
                }
            }

            public Similarity Similarity => m_similarity;

            public int MaxCoord => m_maxCoord;

            public override Query Query => outerInstance;

            public override float GetValueForNormalization()
            {
                float sum = 0.0f;
                for (int i = 0; i < m_weights.Count; i++)
                {
                    // call sumOfSquaredWeights for all clauses in case of side effects
                    float s = m_weights[i].GetValueForNormalization(); // sum sub weights
                    if (!outerInstance.clauses[i].IsProhibited)
                    {
                        // only add to sum for non-prohibited clauses
                        sum += s;
                    }
                }

                sum *= outerInstance.Boost * outerInstance.Boost; // boost each sub-weight

                return sum;
            }

            public virtual float Coord(int overlap, int maxOverlap)
            {
                // LUCENE-4300: in most cases of maxOverlap=1, BQ rewrites itself away,
                // so coord() is not applied. But when BQ cannot optimize itself away
                // for a single clause (minNrShouldMatch, prohibited clauses, etc), its
                // important not to apply coord(1,1) for consistency, it might not be 1.0F
                return maxOverlap == 1 ? 1F : m_similarity.Coord(overlap, maxOverlap);
            }

            public override void Normalize(float norm, float topLevelBoost)
            {
                topLevelBoost *= outerInstance.Boost; // incorporate boost
                foreach (Weight w in m_weights)
                {
                    // normalize all clauses, (even if prohibited in case of side affects)
                    w.Normalize(norm, topLevelBoost);
                }
            }

            public override Explanation Explain(AtomicReaderContext context, int doc)
            {
                int minShouldMatch = outerInstance.MinimumNumberShouldMatch;
                ComplexExplanation sumExpl = new ComplexExplanation();
                sumExpl.Description = "sum of:";
                int coord = 0;
                float sum = 0.0f;
                bool fail = false;
                int shouldMatchCount = 0;
                using (IEnumerator<BooleanClause> cIter = outerInstance.clauses.GetEnumerator())
                {
                    foreach (Weight w in m_weights)
                    {
                        cIter.MoveNext();
                        BooleanClause c = cIter.Current;
                        if (w.GetScorer(context, context.AtomicReader.LiveDocs) is null)
                        {
                            if (c.IsRequired)
                            {
                                fail = true;
                                Explanation r = new Explanation(0.0f, "no match on required clause (" + c.Query.ToString() + ")");
                                sumExpl.AddDetail(r);
                            }
                            continue;
                        }
                        Explanation e = w.Explain(context, doc);
                        if (e.IsMatch)
                        {
                            if (!c.IsProhibited)
                            {
                                sumExpl.AddDetail(e);
                                sum += e.Value;
                                coord++;
                            }
                            else
                            {
                                Explanation r = new Explanation(0.0f, "match on prohibited clause (" + c.Query.ToString() + ")");
                                r.AddDetail(e);
                                sumExpl.AddDetail(r);
                                fail = true;
                            }
                            if (c.Occur == Occur_e.SHOULD)
                            {
                                shouldMatchCount++;
                            }
                        }
                        else if (c.IsRequired)
                        {
                            Explanation r = new Explanation(0.0f, "no match on required clause (" + c.Query.ToString() + ")");
                            r.AddDetail(e);
                            sumExpl.AddDetail(r);
                            fail = true;
                        }
                    }
                }
                if (fail)
                {
                    sumExpl.Match = false;
                    sumExpl.Value = 0.0f;
                    sumExpl.Description = "Failure to meet condition(s) of required/prohibited clause(s)";
                    return sumExpl;
                }
                else if (shouldMatchCount < minShouldMatch)
                {
                    sumExpl.Match = false;
                    sumExpl.Value = 0.0f;
                    sumExpl.Description = "Failure to match minimum number " + "of optional clauses: " + minShouldMatch;
                    return sumExpl;
                }

                sumExpl.Match = 0 < coord ? true : false;
                sumExpl.Value = sum;

                float coordFactor = disableCoord ? 1.0f : Coord(coord, m_maxCoord);
                if (coordFactor == 1.0f)
                {
                    return sumExpl; // eliminate wrapper
                }
                else
                {
                    ComplexExplanation result = new ComplexExplanation(sumExpl.IsMatch, sum * coordFactor, "product of:");
                    result.AddDetail(sumExpl);
                    result.AddDetail(new Explanation(coordFactor, "coord(" + coord + "/" + m_maxCoord + ")"));
                    return result;
                }
            }

            public override BulkScorer GetBulkScorer(AtomicReaderContext context, bool scoreDocsInOrder, IBits acceptDocs)
            {
                if (scoreDocsInOrder || outerInstance.m_minNrShouldMatch > 1)
                {
                    // TODO: (LUCENE-4872) in some cases BooleanScorer may be faster for minNrShouldMatch
                    // but the same is even true of pure conjunctions...
                    return base.GetBulkScorer(context, scoreDocsInOrder, acceptDocs);
                }

                IList<BulkScorer> prohibited = new JCG.List<BulkScorer>();
                IList<BulkScorer> optional = new JCG.List<BulkScorer>();
                using (IEnumerator<BooleanClause> cIter = outerInstance.clauses.GetEnumerator())
                {
                    foreach (Weight w in m_weights)
                    {
                        cIter.MoveNext();
                        BooleanClause c = cIter.Current;
                        BulkScorer subScorer = w.GetBulkScorer(context, false, acceptDocs);
                        if (subScorer is null)
                        {
                            if (c.IsRequired)
                            {
                                return null;
                            }
                        }
                        else if (c.IsRequired)
                        {
                            // TODO: there are some cases where BooleanScorer
                            // would handle conjunctions faster than
                            // BooleanScorer2...
                            return base.GetBulkScorer(context, scoreDocsInOrder, acceptDocs);
                        }
                        else if (c.IsProhibited)
                        {
                            prohibited.Add(subScorer);
                        }
                        else
                        {
                            optional.Add(subScorer);
                        }
                    }
                }

                // Check if we can and should return a BooleanScorer
                return new BooleanScorer(this, disableCoord, outerInstance.m_minNrShouldMatch, optional, prohibited, m_maxCoord);
            }

            public override Scorer GetScorer(AtomicReaderContext context, IBits acceptDocs)
            {
                IList<Scorer> required = new JCG.List<Scorer>();
                IList<Scorer> prohibited = new JCG.List<Scorer>();
                IList<Scorer> optional = new JCG.List<Scorer>();
                IEnumerator<BooleanClause> cIter = outerInstance.clauses.GetEnumerator();
                foreach (Weight w in m_weights)
                {
                    cIter.MoveNext();
                    BooleanClause c = cIter.Current;
                    Scorer subScorer = w.GetScorer(context, acceptDocs);
                    if (subScorer is null)
                    {
                        if (c.IsRequired)
                        {
                            return null;
                        }
                    }
                    else if (c.IsRequired)
                    {
                        required.Add(subScorer);
                    }
                    else if (c.IsProhibited)
                    {
                        prohibited.Add(subScorer);
                    }
                    else
                    {
                        optional.Add(subScorer);
                    }
                }

                if (required.Count == 0 && optional.Count == 0)
                {
                    // no required and optional clauses.
                    return null;
                }
                else if (optional.Count < outerInstance.m_minNrShouldMatch)
                {
                    // either >1 req scorer, or there are 0 req scorers and at least 1
                    // optional scorer. Therefore if there are not enough optional scorers
                    // no documents will be matched by the query
                    return null;
                }

                // simple conjunction
                if (optional.Count == 0 && prohibited.Count == 0)
                {
                    float coord = disableCoord ? 1.0f : Coord(required.Count, m_maxCoord);
                    return new ConjunctionScorer(this, required.ToArray(), coord);
                }

                // simple disjunction
                if (required.Count == 0 && prohibited.Count == 0 && outerInstance.m_minNrShouldMatch <= 1 && optional.Count > 1)
                {
                    var coord = new float[optional.Count + 1];
                    for (int i = 0; i < coord.Length; i++)
                    {
                        coord[i] = disableCoord ? 1.0f : Coord(i, m_maxCoord);
                    }
                    return new DisjunctionSumScorer(this, optional.ToArray(), coord);
                }

                // Return a BooleanScorer2
                return new BooleanScorer2(this, disableCoord, outerInstance.m_minNrShouldMatch, required, prohibited, optional, m_maxCoord);
            }

            public override bool ScoresDocsOutOfOrder
            {
                get
                {
                    if (outerInstance.m_minNrShouldMatch > 1)
                    {
                        // BS2 (in-order) will be used by scorer()
                        return false;
                    }
                    foreach (BooleanClause c in outerInstance.clauses)
                    {
                        if (c.IsRequired)
                        {
                            // BS2 (in-order) will be used by scorer()
                            return false;
                        }
                    }

                    // scorer() will return an out-of-order scorer if requested.
                    return true;
                }
            }
        }

        public override Weight CreateWeight(IndexSearcher searcher)
        {
            return new BooleanWeight(this, searcher, disableCoord);
        }

        public override Query Rewrite(IndexReader reader)
        {
            if (m_minNrShouldMatch == 0 && clauses.Count == 1) // optimize 1-clause queries
            {
                BooleanClause c = clauses[0];
                if (!c.IsProhibited) // just return clause
                {
                    Query query = c.Query.Rewrite(reader); // rewrite first

                    if (Boost != 1.0f) // incorporate boost
                    {
                        if (query == c.Query) // if rewrite was no-op
                        {
                            query = (Query)query.Clone(); // then clone before boost
                        }
                        // Since the BooleanQuery only has 1 clause, the BooleanQuery will be
                        // written out. Therefore the rewritten Query's boost must incorporate both
                        // the clause's boost, and the boost of the BooleanQuery itself
                        query.Boost = Boost * query.Boost;
                    }

                    return query;
                }
            }

            BooleanQuery clone = null; // recursively rewrite
            for (int i = 0; i < clauses.Count; i++)
            {
                BooleanClause c = clauses[i];
                Query query = c.Query.Rewrite(reader);
                if (query != c.Query) // clause rewrote: must clone
                {
                    if (clone is null)
                    {
                        // The BooleanQuery clone is lazily initialized so only initialize
                        // it if a rewritten clause differs from the original clause (and hasn't been
                        // initialized already).  If nothing differs, the clone isn't needlessly created
                        clone = (BooleanQuery)this.Clone();
                    }
                    clone.clauses[i] = new BooleanClause(query, c.Occur);
                }
            }
            if (clone != null)
            {
                return clone; // some clauses rewrote
            }
            else
            {
                return this; // no clauses rewrote
            }
        }

        // inherit javadoc
        public override void ExtractTerms(ISet<Term> terms)
        {
            foreach (BooleanClause clause in clauses)
            {
                if (clause.Occur != Occur_e.MUST_NOT)
                {
                    clause.Query.ExtractTerms(terms);
                }
            }
        }

        public override object Clone()
        {
            BooleanQuery clone = (BooleanQuery)base.Clone();
            clone.clauses = new JCG.List<BooleanClause>(this.clauses);
            return clone;
        }

        /// <summary>
        /// Prints a user-readable version of this query. </summary>
        public override string ToString(string field)
        {
            StringBuilder buffer = new StringBuilder();
            bool needParens = Boost != 1.0 || MinimumNumberShouldMatch > 0;
            if (needParens)
            {
                buffer.Append('(');
            }

            for (int i = 0; i < clauses.Count; i++)
            {
                BooleanClause c = clauses[i];
                if (c.IsProhibited)
                {
                    buffer.Append('-');
                }
                else if (c.IsRequired)
                {
                    buffer.Append('+');
                }

                Query subQuery = c.Query;
                if (subQuery != null)
                {
                    if (subQuery is BooleanQuery) // wrap sub-bools in parens
                    {
                        buffer.Append('(');
                        buffer.Append(subQuery.ToString(field));
                        buffer.Append(')');
                    }
                    else
                    {
                        buffer.Append(subQuery.ToString(field));
                    }
                }
                else
                {
                    buffer.Append("null");
                }

                if (i != clauses.Count - 1)
                {
                    buffer.Append(' ');
                }
            }

            if (needParens)
            {
                buffer.Append(')');
            }

            if (MinimumNumberShouldMatch > 0)
            {
                buffer.Append('~');
                buffer.Append(MinimumNumberShouldMatch);
            }

            if (Boost != 1.0f)
            {
                buffer.Append(ToStringUtils.Boost(Boost));
            }

            return buffer.ToString();
        }

        /// <summary>
        /// Returns <c>true</c> if <paramref name="o"/> is equal to this. </summary>
        public override bool Equals(object o)
        {
            if (o is not BooleanQuery other)
            {
                return false;
            }

            // LUCENENET specific - compare bits rather than using equality operators to prevent these comparisons from failing in x86 in .NET Framework with optimizations enabled
            return NumericUtils.SingleToSortableInt32(this.Boost) == NumericUtils.SingleToSortableInt32(other.Boost)
                && this.clauses.Equals(other.clauses)
                && this.MinimumNumberShouldMatch == other.MinimumNumberShouldMatch
                && this.disableCoord == other.disableCoord;
        }

        /// <summary>
        /// Returns a hash code value for this object. </summary>
        public override int GetHashCode()
        {
            unchecked
            {
                return BitConversion.SingleToInt32Bits(Boost) ^ clauses.GetHashCode()
                    + MinimumNumberShouldMatch + (disableCoord ? 17 : 0);
            }
        }
    }
}
