﻿/*
 * 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 System;
using Lucene.Net.Documents;
using Lucene.Net.Search;
using Lucene.Net.Search.Function;
using Lucene.Net.Search.Function.ValueSources;
using Lucene.Net.Spatial.Queries;
using Lucene.Net.Spatial.Util;
using Spatial4n.Core.Context;
using Spatial4n.Core.Shapes;

namespace Lucene.Net.Spatial
{
    /// <summary>
    /// The SpatialStrategy encapsulates an approach to indexing and searching based on shapes.
    /// <p/>
    /// Note that a SpatialStrategy is not involved with the Lucene stored field values of shapes, which is
    /// immaterial to indexing and search.
    /// <p/>
    /// Thread-safe.
    /// </summary>
    public abstract class SpatialStrategy
    {
        protected readonly SpatialContext ctx;
        protected readonly string fieldName;

        /// <summary>
        /// Constructs the spatial strategy with its mandatory arguments.
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="fieldName"> </param>
        protected SpatialStrategy(SpatialContext ctx, string fieldName)
        {
            if (ctx == null)
                throw new ArgumentException("ctx is required", "ctx");
            this.ctx = ctx;
            if (string.IsNullOrEmpty(fieldName))
                throw new ArgumentException("fieldName is required", "fieldName");
            this.fieldName = fieldName;
        }

        public SpatialContext SpatialContext
        {
            get { return ctx; }
        }

        /// <summary>
        /// The name of the field or the prefix of them if there are multiple
        /// fields needed internally.
        /// </summary>
        /// <returns></returns>
        public String FieldName
        {
            get { return fieldName; }
        }

        /// <summary>
        /// Returns the IndexableField(s) from the <c>shape</c> that are to be
        /// added to the {@link org.apache.lucene.document.Document}.  These fields
        /// are expected to be marked as indexed and not stored.
        /// <p/>
        /// Note: If you want to <i>store</i> the shape as a string for retrieval in search
        /// results, you could add it like this:
        /// <pre>document.add(new StoredField(fieldName,ctx.toString(shape)));</pre>
        /// The particular string representation used doesn't matter to the Strategy since it
        /// doesn't use it.
        /// </summary>
        /// <param name="shape"></param>
        /// <returns>Not null nor will it have null elements.</returns>
        public abstract Field[] CreateIndexableFields(Shape shape);

        public Field CreateStoredField(Shape shape)
        {
            return new Field(FieldName, ctx.ToString(shape), Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS, Field.TermVector.NO);
        }

        /// <summary>
        /// Make a ValueSource returning the distance between the center of the
        /// indexed shape and {@code queryPoint}.  If there are multiple indexed shapes
        /// then the closest one is chosen.
        /// </summary>
        public abstract ValueSource MakeDistanceValueSource(Point queryPoint);

        /// <summary>
        /// Make a (ConstantScore) Query based principally on {@link org.apache.lucene.spatial.query.SpatialOperation}
        /// and {@link Shape} from the supplied {@code args}.
        /// The default implementation is
        /// <pre>return new ConstantScoreQuery(makeFilter(args));</pre>
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        public virtual ConstantScoreQuery MakeQuery(SpatialArgs args)
        {
            return new ConstantScoreQuery(MakeFilter(args));
        }

        /// <summary>
        /// Make a Filter based principally on {@link org.apache.lucene.spatial.query.SpatialOperation}
        /// and {@link Shape} from the supplied {@code args}.
        /// <p />
        /// If a subclasses implements
        /// {@link #makeQuery(org.apache.lucene.spatial.query.SpatialArgs)}
        /// then this method could be simply:
        /// <pre>return new QueryWrapperFilter(makeQuery(args).getQuery());</pre>
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        public abstract Filter MakeFilter(SpatialArgs args);

        /// <summary>
        /// Returns a ValueSource with values ranging from 1 to 0, depending inversely
        /// on the distance from {@link #makeDistanceValueSource(com.spatial4j.core.shape.Point)}.
        /// The formula is <c>c/(d + c)</c> where 'd' is the distance and 'c' is
        /// one tenth the distance to the farthest edge from the center. Thus the
        /// scores will be 1 for indexed points at the center of the query shape and as
        /// low as ~0.1 at its furthest edges.
        /// </summary>
        /// <param name="queryShape"></param>
        /// <returns></returns>
        public ValueSource MakeRecipDistanceValueSource(Shape queryShape)
        {
            Rectangle bbox = queryShape.GetBoundingBox();
            double diagonalDist = ctx.GetDistCalc().Distance(
                ctx.MakePoint(bbox.GetMinX(), bbox.GetMinY()), bbox.GetMaxX(), bbox.GetMaxY());
            double distToEdge = diagonalDist * 0.5;
            float c = (float)distToEdge * 0.1f; //one tenth
            return new ReciprocalFloatFunction(MakeDistanceValueSource(queryShape.GetCenter()), 1f, c, c);
        }

        public override string ToString()
        {
            return GetType().Name + " field:" + fieldName + " ctx=" + ctx;
        }
    }
}
