﻿using J2N.Runtime.CompilerServices;
using Lucene.Net.Index;
using Lucene.Net.Search;
using System;
using System.Collections;

namespace Lucene.Net.Queries.Function
{
    /*
     * 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>
    /// Instantiates <see cref="FunctionValues"/> for a particular reader.
    /// <para/>
    /// Often used when creating a <see cref="FunctionQuery"/>.
    /// </summary>
    public abstract class ValueSource
    {
        /// <summary>
        /// Gets the values for this reader and the context that was previously
        /// passed to <see cref="CreateWeight"/>
        /// </summary>
        public abstract FunctionValues GetValues(IDictionary context, AtomicReaderContext readerContext); // LUCENENET TODO: API - See if we can use generic IDictionary here instead

        public override abstract bool Equals(object o);

        public override abstract int GetHashCode();

        /// <summary>
        /// description of field, used in Explain()
        /// </summary>
        public abstract string GetDescription();

        public override string ToString()
        {
            return GetDescription();
        }


        /// <summary>
        /// Implementations should propagate CreateWeight to sub-ValueSources which can optionally store
        /// weight info in the context. The context object will be passed to GetValues()
        /// where this info can be retrieved.
        /// </summary>
        public virtual void CreateWeight(IDictionary context, IndexSearcher searcher)
        {
        }

        /// <summary>
        /// Returns a new non-threadsafe context map.
        /// </summary>
        public static IDictionary NewContext(IndexSearcher searcher)
        {
            return new Hashtable(IdentityEqualityComparer<object>.Default)
            {
                ["searcher"] = searcher
            };
        }


        //
        // Sorting by function
        //

        /// <summary>
        /// EXPERIMENTAL: This method is subject to change.
        /// <para/>
        /// Get the <see cref="SortField"/> for this <see cref="ValueSource"/>.  Uses the <see cref="GetValues(IDictionary, AtomicReaderContext)"/>
        /// to populate the <see cref="SortField"/>.
        /// </summary>
        /// <param name="reverse"> <c>true</c> if this is a reverse sort. </param>
        /// <returns> The <see cref="SortField"/> for the <see cref="ValueSource"/> </returns>
        public virtual SortField GetSortField(bool reverse)
        {
            return new ValueSourceSortField(this, reverse);
        }

        internal class ValueSourceSortField : SortField
        {
            private readonly ValueSource outerInstance;

            public ValueSourceSortField(ValueSource outerInstance, bool reverse)
                : base(outerInstance.GetDescription(), SortFieldType.REWRITEABLE, reverse)
            {
                this.outerInstance = outerInstance;
            }

            public override SortField Rewrite(IndexSearcher searcher)
            {
                var context = NewContext(searcher);
                outerInstance.CreateWeight(context, searcher);
                return new SortField(Field, new ValueSourceComparerSource(outerInstance, context), IsReverse);
            }
        }

        internal class ValueSourceComparerSource : FieldComparerSource
        {
            private readonly ValueSource outerInstance;

            private readonly IDictionary context;

            public ValueSourceComparerSource(ValueSource outerInstance, IDictionary context)
            {
                this.outerInstance = outerInstance;
                this.context = context;
            }

            public override FieldComparer NewComparer(string fieldname, int numHits, int sortPos, bool reversed)
            {
                return new ValueSourceComparer(outerInstance, context, numHits);
            }
        }

        /// <summary>
        /// Implement a <see cref="FieldComparer"/> that works
        /// off of the <see cref="FunctionValues"/> for a <see cref="ValueSource"/>
        /// instead of the normal Lucene <see cref="FieldComparer"/> that works off of a <see cref="FieldCache"/>.
        /// </summary>
        internal class ValueSourceComparer : FieldComparer<double?>
        {
            private readonly ValueSource outerInstance;

            private readonly double[] values;
            private FunctionValues docVals;
            private double bottom;
            private readonly IDictionary fcontext;
            private double topValue;

            internal ValueSourceComparer(ValueSource outerInstance, IDictionary fcontext, int numHits)
            {
                this.outerInstance = outerInstance;
                this.fcontext = fcontext;
                values = new double[numHits];
            }

            public override int Compare(int slot1, int slot2)
            {
                return values[slot1].CompareTo(values[slot2]);
            }

            public override int CompareBottom(int doc)
            {
                return bottom.CompareTo(docVals.DoubleVal(doc));
            }

            public override void Copy(int slot, int doc)
            {
                values[slot] = docVals.DoubleVal(doc);
            }

            public override FieldComparer SetNextReader(AtomicReaderContext context)
            {
                docVals = outerInstance.GetValues(fcontext, context);
                return this;
            }

            public override void SetBottom(int slot)
            {
                this.bottom = values[slot];
            }

            public override void SetTopValue(object value)
            {
                this.topValue = (double)value;
            }

            // LUCENENET NOTE: This was value(int) in Lucene.
            public override IComparable this[int slot] => values[slot];

            public override int CompareTop(int doc)
            {
                double docValue = docVals.DoubleVal(doc);
                return topValue.CompareTo(docValue);
            }
        }
    }
}