using Lucene.Net.Expressions.JS;
using Lucene.Net.Search;
using Lucene.Net.Util;
using NUnit.Framework;

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

    public class TestExpressionSortField : LuceneTestCase
	{
		[Test]
		public virtual void TestToString()
		{
			Expression expr = JavascriptCompiler.Compile("sqrt(_score) + ln(popularity)");
			SimpleBindings bindings = new SimpleBindings();
			bindings.Add(new SortField("_score", SortFieldType.SCORE));
			bindings.Add(new SortField("popularity", SortFieldType.INT32));
			SortField sf = expr.GetSortField(bindings, true);
            Assert.AreEqual("<expr \"sqrt(_score) + ln(popularity)\">!", sf.ToString());
		}

		[Test]
		public virtual void TestEquals()
		{
			Expression expr = JavascriptCompiler.Compile("sqrt(_score) + ln(popularity)");
			SimpleBindings bindings = new SimpleBindings();
			bindings.Add(new SortField("_score", SortFieldType.SCORE));
			bindings.Add(new SortField("popularity", SortFieldType.INT32));
			SimpleBindings otherBindings = new SimpleBindings();
			otherBindings.Add(new SortField("_score", SortFieldType.INT64));
			otherBindings.Add(new SortField("popularity", SortFieldType.INT32));
			SortField sf1 = expr.GetSortField(bindings, true);
			// different order
			SortField sf2 = expr.GetSortField(bindings, false);
            Assert.IsFalse(sf1.Equals(sf2));
			// different bindings
			sf2 = expr.GetSortField(otherBindings, true);
            Assert.IsFalse(sf1.Equals(sf2));
			// different expression
			Expression other = JavascriptCompiler.Compile("popularity/2");
			sf2 = other.GetSortField(bindings, true);
            Assert.IsFalse(sf1.Equals(sf2));
            // null
            Assert.IsFalse(sf1.Equals(null));
            // same instance:
            Assert.AreEqual(sf1, sf1);
		}

		[Test]
		public virtual void TestNeedsScores()
		{
			SimpleBindings bindings = new SimpleBindings();
			// refers to score directly
			Expression exprA = JavascriptCompiler.Compile("_score");
			// constant
			Expression exprB = JavascriptCompiler.Compile("0");
			// field
			Expression exprC = JavascriptCompiler.Compile("intfield");
			// score + constant
			Expression exprD = JavascriptCompiler.Compile("_score + 0");
			// field + constant
			Expression exprE = JavascriptCompiler.Compile("intfield + 0");
			// expression + constant (score ref'd)
			Expression exprF = JavascriptCompiler.Compile("a + 0");
			// expression + constant
			Expression exprG = JavascriptCompiler.Compile("e + 0");
			// several variables (score ref'd)
			Expression exprH = JavascriptCompiler.Compile("b / c + e * g - sqrt(f)");
			// several variables
			Expression exprI = JavascriptCompiler.Compile("b / c + e * g");
			bindings.Add(new SortField("_score", SortFieldType.SCORE));
			bindings.Add(new SortField("intfield", SortFieldType.INT32));
			bindings.Add("a", exprA);
			bindings.Add("b", exprB);
			bindings.Add("c", exprC);
			bindings.Add("d", exprD);
			bindings.Add("e", exprE);
			bindings.Add("f", exprF);
			bindings.Add("g", exprG);
			bindings.Add("h", exprH);
			bindings.Add("i", exprI);
            Assert.IsTrue(exprA.GetSortField(bindings, true).NeedsScores);
            Assert.IsFalse(exprB.GetSortField(bindings, true).NeedsScores);
            Assert.IsFalse(exprC.GetSortField(bindings, true).NeedsScores);
            Assert.IsTrue(exprD.GetSortField(bindings, true).NeedsScores);
            Assert.IsFalse(exprE.GetSortField(bindings, true).NeedsScores);
            Assert.IsTrue(exprF.GetSortField(bindings, true).NeedsScores);
            Assert.IsFalse(exprG.GetSortField(bindings, true).NeedsScores);
            Assert.IsTrue(exprH.GetSortField(bindings, true).NeedsScores);
            Assert.IsFalse(exprI.GetSortField(bindings, false).NeedsScores);
		}
	}
}
