﻿using Lucene.Net.Randomized.Generators;
using Lucene.Net.Spatial.Prefix;
using Lucene.Net.Spatial.Prefix.Tree;
using Lucene.Net.Spatial.Serialized;
using Lucene.Net.Spatial.Vector;
using Lucene.Net.Support;
using NUnit.Framework;
using Spatial4n.Core.Context;
using Spatial4n.Core.Shapes;
using System;
using System.Collections.Generic;

namespace Lucene.Net.Spatial
{
    /*
     * 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 DistanceStrategyTest : StrategyTestCase
    {
        //@ParametersFactory
        public static IList<Object[]> Parameters()
        {
            List<Object[]> ctorArgs = new List<object[]>();

            SpatialContext ctx = SpatialContext.GEO;
            SpatialPrefixTree grid;
            SpatialStrategy strategy;

            grid = new QuadPrefixTree(ctx, 25);
            strategy = new RecursivePrefixTreeStrategy(grid, "recursive_quad");
            ctorArgs.Add(new Object[] { new Param(strategy) });

            grid = new GeohashPrefixTree(ctx, 12);
            strategy = new TermQueryPrefixTreeStrategy(grid, "termquery_geohash");
            ctorArgs.Add(new Object[] { new Param(strategy) });

            strategy = new PointVectorStrategy(ctx, "pointvector");
            ctorArgs.Add(new Object[] { new Param(strategy) });

            strategy = new SerializedDVStrategy(ctx, "serialized");
            ctorArgs.Add(new Object[] { new Param(strategy) });

            return ctorArgs;
        }

        // this is a hack for clover!
        public class Param
        {
            internal SpatialStrategy strategy;

            internal Param(SpatialStrategy strategy)
            {
                this.strategy = strategy;
            }


            public override String ToString()
            {
                return strategy.FieldName;
            }
        }

        //  private String fieldName;

        //public DistanceStrategyTest(Param param)
        //{
        //    SpatialStrategy strategy = param.strategy;
        //    this.ctx = strategy.SpatialContext;
        //    this.strategy = strategy;
        //}

        public override void SetUp()
        {
            SpatialStrategy strategy = ((Param)(RandomInts.RandomFrom(Random(), Parameters()))[0]).strategy;
            this.ctx = strategy.SpatialContext;
            this.strategy = strategy;
            base.SetUp();
        }


        protected override bool NeedsDocValues()
        {
            return (strategy is SerializedDVStrategy);
        }

        [Test]
        public virtual void TestDistanceOrder()
        {
            adoc("100", ctx.MakePoint(2, 1));
            adoc("101", ctx.MakePoint(-1, 4));
            adoc("103", (IShape)null);//test score for nothing
            adoc("999", ctx.MakePoint(2, 1));//test deleted
            Commit();
            DeleteDoc("999");
            Commit();
            //FYI distances are in docid order
            checkDistValueSource(ctx.MakePoint(4, 3), 2.8274937f, 5.0898066f, 180f);
            checkDistValueSource(ctx.MakePoint(0, 4), 3.6043684f, 0.9975641f, 180f);
        }

        [Test]
        public virtual void TestRecipScore()
        {
            IPoint p100 = ctx.MakePoint(2, 1);
            adoc("100", p100);
            IPoint p101 = ctx.MakePoint(-1, 4);
            adoc("101", p101);
            adoc("103", (IShape)null);//test score for nothing
            adoc("999", ctx.MakePoint(2, 1));//test deleted
            Commit();
            DeleteDoc("999");
            Commit();

            double dist = ctx.DistCalc.Distance(p100, p101);
            IShape queryShape = ctx.MakeCircle(2.01, 0.99, dist);
            CheckValueSource(strategy.MakeRecipDistanceValueSource(queryShape),
            new float[] { 1.00f, 0.10f, 0f }, 0.09f);
        }

        // @Override
        // protected Document newDoc(String id, Shape shape) {
        //   //called by adoc().  Make compatible with BBoxStrategy.
        //   if (shape != null && strategy instanceof BBoxStrategy)
        //     shape = ctx.makeRectangle(shape.getCenter(), shape.getCenter());
        //   return super.newDoc(id, shape);
        // }

        internal void checkDistValueSource(IPoint pt, params float[] distances)
        {
            float multiplier = (float)Random().NextDouble() * 100f;
            float[]
            dists2 = Arrays.CopyOf(distances, distances.Length);
            for (int i = 0; i < dists2.Length; i++)
            {
                dists2[i] *= multiplier;
            }
            CheckValueSource(strategy.MakeDistanceValueSource(pt, multiplier), dists2, 1.0e-3f);
        }

    }
}
