// Lucene version compatibility level 4.8.1
using System;
using Lucene.Net.Analysis;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.Index.Extensions;
using Lucene.Net.Queries.Function;
using Lucene.Net.Queries.Function.ValueSources;
using Lucene.Net.Store;
using Lucene.Net.Util;
using NUnit.Framework;

namespace Lucene.Net.Tests.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>
    /// Setup for function tests
    /// </summary>
    public abstract class FunctionTestSetup : LuceneTestCase
    {

        /// <summary>
        /// Actual score computation order is slightly different than assumptios
        /// this allows for a small amount of variation
        /// </summary>
        protected const float TEST_SCORE_TOLERANCE_DELTA = 0.001f;

        protected const int N_DOCS = 17; // select a primary number > 2

        protected const string ID_FIELD = "id";
        protected const string TEXT_FIELD = "text";
        protected const string INT_FIELD = "iii";
        protected const string FLOAT_FIELD = "fff";

#pragma warning disable 612, 618
        protected ValueSource BYTE_VALUESOURCE = new ByteFieldSource(INT_FIELD);
        protected ValueSource SHORT_VALUESOURCE = new Int16FieldSource(INT_FIELD);
#pragma warning restore 612, 618
        protected ValueSource INT_VALUESOURCE = new Int32FieldSource(INT_FIELD);
        protected ValueSource INT_AS_FLOAT_VALUESOURCE = new SingleFieldSource(INT_FIELD);
        protected ValueSource FLOAT_VALUESOURCE = new SingleFieldSource(FLOAT_FIELD);

        private static readonly string[] DOC_TEXT_LINES =
        {
            @"Well, this is just some plain text we use for creating the ",
            "test documents. It used to be a text from an online collection ",
            "devoted to first aid, but if there was there an (online) lawyers ",
            "first aid collection with legal advices, \"it\" might have quite ",
            "probably advised one not to include \"it\"'s text or the text of ",
            "any other online collection in one's code, unless one has money ",
            "that one don't need and one is happy to donate for lawyers ",
            "charity. Anyhow at some point, rechecking the usage of this text, ",
            "it became uncertain that this text is free to use, because ",
            "the web site in the disclaimer of he eBook containing that text ",
            "was not responding anymore, and at the same time, in projGut, ",
            "searching for first aid no longer found that eBook as well. ",
            "So here we are, with a perhaps much less interesting ",
            "text for the test, but oh much much safer. "
        };

        protected static Directory dir;
        protected static Analyzer anlzr;

        [TearDown]
        public override void TearDown()
        {
            dir.Dispose();
            dir = null;
            anlzr = null;
            base.TearDown();
        }

        /// <summary>
        /// LUCENENET specific
        /// Non-static because NewIndexWriterConfig is now non-static
        /// </summary>
        protected internal void CreateIndex(bool doMultiSegment)
        {
            if (Verbose)
            {
                Console.WriteLine("TEST: setUp");
            }
            // prepare a small index with just a few documents.
            dir = NewDirectory();
            anlzr = new MockAnalyzer(Random);
            IndexWriterConfig iwc = NewIndexWriterConfig(TEST_VERSION_CURRENT, anlzr).SetMergePolicy(NewLogMergePolicy());
            if (doMultiSegment)
            {
                iwc.SetMaxBufferedDocs(TestUtil.NextInt32(Random, 2, 7));
            }
            RandomIndexWriter iw = new RandomIndexWriter(Random, dir, iwc);
            // add docs not exactly in natural ID order, to verify we do check the order of docs by scores
            int remaining = N_DOCS;
            bool[] done = new bool[N_DOCS];
            int i = 0;
            while (remaining > 0)
            {
                if (done[i])
                {
                    throw new Exception("to set this test correctly N_DOCS=" + N_DOCS + " must be primary and greater than 2!");
                }
                AddDoc(iw, i);
                done[i] = true;
                i = (i + 4) % N_DOCS;
                remaining--;
            }
            if (!doMultiSegment)
            {
                if (Verbose)
                {
                    Console.WriteLine("TEST: setUp full merge");
                }
                iw.ForceMerge(1);
            }
            iw.Dispose();
            if (Verbose)
            {
                Console.WriteLine("TEST: setUp done close");
            }
        }

        private static void AddDoc(RandomIndexWriter iw, int i)
        {
            Document d = new Document();
            Field f;
            int scoreAndID = i + 1;

            FieldType customType = new FieldType(TextField.TYPE_STORED);
            customType.IsTokenized = false;
            customType.OmitNorms = true;

            f = NewField(ID_FIELD, Id2String(scoreAndID), customType); // for debug purposes
            d.Add(f);

            FieldType customType2 = new FieldType(TextField.TYPE_NOT_STORED);
            customType2.OmitNorms = true;
            f = NewField(TEXT_FIELD, "text of doc" + scoreAndID + TextLine(i), customType2); // for regular search
            d.Add(f);

            f = NewField(INT_FIELD, "" + scoreAndID, customType); // for function scoring
            d.Add(f);

            f = NewField(FLOAT_FIELD, scoreAndID + ".000", customType); // for function scoring
            d.Add(f);

            iw.AddDocument(d);
            Log("added: " + d);
        }

        // 17 --> ID00017
        protected static string Id2String(int scoreAndID)
        {
            string s = "000000000" + scoreAndID;
            int n = ("" + N_DOCS).Length + 3;
            int k = s.Length - n;
            return "ID" + s.Substring(k);
        }

        // some text line for regular search
        private static string TextLine(int docNum)
        {
            return DOC_TEXT_LINES[docNum % DOC_TEXT_LINES.Length];
        }

        // extract expected doc score from its ID Field: "ID7" --> 7.0
        protected static float ExpectedFieldScore(string docIDFieldVal)
        {
            return Convert.ToSingle(docIDFieldVal.Substring(2));
        }

        // debug messages (change DBG to true for anything to print)
        protected static void Log(object o)
        {
            if (Verbose)
            {
                Console.WriteLine(o.ToString());
            }
        }
    }
}
