/* 
 * 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 System.Collections.Generic;
using Spatial4n.Core.Context;
using Spatial4n.Core.Distance;

namespace Lucene.Net.Spatial.Prefix.Tree
{
    /// <summary>
    /// Abstract Factory for creating
    /// <see cref="SpatialPrefixTree">SpatialPrefixTree</see>
    /// instances with useful
    /// defaults and passed on configurations defined in a Map.
    /// </summary>
    /// <lucene.experimental></lucene.experimental>
    public abstract class SpatialPrefixTreeFactory
    {
        private const double DefaultGeoMaxDetailKm = 0.001;

        public const string PrefixTree = "prefixTree";

        public const string MaxLevels = "maxLevels";

        public const string MaxDistErr = "maxDistErr";

        protected internal IDictionary<string, string> args;

        protected internal SpatialContext ctx;

        protected internal int? maxLevels;

        //1m
        /// <summary>The factory  is looked up via "prefixTree" in args, expecting "geohash" or "quad".
        /// 	</summary>
        /// <remarks>
        /// The factory  is looked up via "prefixTree" in args, expecting "geohash" or "quad".
        /// If its neither of these, then "geohash" is chosen for a geo context, otherwise "quad" is chosen.
        /// </remarks>
        public static SpatialPrefixTree MakeSPT(IDictionary<string, string> args, SpatialContext ctx)
        {
            SpatialPrefixTreeFactory instance;
            string cname = args[PrefixTree];
            if (cname == null)
            {
                cname = ctx.IsGeo() ? "geohash" : "quad";
            }
            if ("geohash".Equals(cname, StringComparison.OrdinalIgnoreCase))
            {
                instance = new GeohashPrefixTree.Factory();
            }
            else
            {
                if ("quad".Equals(cname, StringComparison.OrdinalIgnoreCase))
                {
                    instance = new QuadPrefixTree.Factory();
                }
                else
                {
                    try
                    {
                        Type c = Type.GetType(cname);
                        instance = (SpatialPrefixTreeFactory)System.Activator.CreateInstance(c);
                    }
                    catch (Exception e)
                    {
                        throw new Exception(string.Empty, e);
                    }
                }
            }
            instance.Init(args, ctx);
            return instance.NewSPT();
        }

        protected internal virtual void Init(IDictionary<string, string> args, SpatialContext
             ctx)
        {
            this.args = args;
            this.ctx = ctx;
            InitMaxLevels();
        }

        protected internal virtual void InitMaxLevels()
        {
            string mlStr = args[MaxLevels];
            if (mlStr != null)
            {
                maxLevels = int.Parse(mlStr);
                return;
            }
            double degrees;
            string maxDetailDistStr = args[MaxDistErr];
            if (maxDetailDistStr == null)
            {
                if (!ctx.IsGeo())
                {
                    return;
                }
                //let default to max
                degrees = DistanceUtils.Dist2Degrees(DefaultGeoMaxDetailKm, DistanceUtils.EARTH_MEAN_RADIUS_KM);
            }
            else
            {
                degrees = double.Parse(maxDetailDistStr);
            }
            maxLevels = GetLevelForDistance(degrees);
        }

        /// <summary>
        /// Calls
        /// <see cref="SpatialPrefixTree.GetLevelForDistance(double)">SpatialPrefixTree.GetLevelForDistance(double)
        /// 	</see>
        /// .
        /// </summary>
        protected internal abstract int GetLevelForDistance(double degrees);

        protected internal abstract SpatialPrefixTree NewSPT();
    }
}
