﻿// 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 System.Reflection;
using Org.Apache.REEF.Tang.Exceptions;
using Org.Apache.REEF.Tang.Interface;
using Org.Apache.REEF.Tang.Util;
using Org.Apache.REEF.Utilities.Logging;

namespace Org.Apache.REEF.Tang.Formats
{
    /**
     * Allows applications to bundle sets of configuration options together into 
     * discrete packages.  Unlike more conventional approaches,
     * ConfigurationModules store such information in static data structures that
     * can be statically discovered and sanity-checked. 
     * 
     * @see Org.Apache.REEF.Tang.Formats.TestConfigurationModule for more information and examples.
     *
     */
    public class ConfigurationModule
    {
        public readonly ConfigurationModuleBuilder Builder;
        private static readonly Logger LOGGER = Logger.GetLogger(typeof(ConfigurationModule));
        private readonly MonotonicHashSet<FieldInfo> reqSet = new MonotonicHashSet<FieldInfo>();
        private readonly MonotonicHashMap<object, Type> setImpls = new MonotonicHashMap<object, Type>();
        private readonly MonotonicMultiHashMap<object, Type> setImplSets = new MonotonicMultiHashMap<object, Type>();
        private readonly MonotonicMultiHashMap<object, string> setLateImplSets = new MonotonicMultiHashMap<object, string>();
        private readonly MonotonicMultiHashMap<object, string> setParamSets = new MonotonicMultiHashMap<object, string>();
        private readonly MonotonicHashMap<object, string> setLateImpls = new MonotonicHashMap<object, string>();
        private readonly MonotonicHashMap<object, string> setParams = new MonotonicHashMap<object, string>();

        private readonly MonotonicHashMap<object, IList<Type>> setImplLists = new MonotonicHashMap<object, IList<Type>>();
        private readonly MonotonicHashMap<object, IList<string>> setParamLists = new MonotonicHashMap<object, IList<string>>();
        private readonly MonotonicHashMap<object, IList<string>> setLateImplLists = new MonotonicHashMap<object, IList<string>>();
        
        public ConfigurationModule(ConfigurationModuleBuilder builder) 
        {
            this.Builder = builder.DeepCopy();
        }

        public ConfigurationModule Set<T, U>(IImpl<T> opt, GenericType<U> impl) 
            where U : T 
        {
            Type implType = typeof(U);
            
            ConfigurationModule c = DeepCopy();
            c.ProcessSet(opt);
            if (c.Builder.SetOpts.Contains(opt)) 
            {
                c.setImplSets.Add(opt, implType);
            } 
            else 
            {
                c.setImpls.Add(opt, implType);
            }
            return c;
        }

        public ConfigurationModule Set<T>(IImpl<T> opt, string impl) 
        {
            ConfigurationModule c = DeepCopy();
            c.ProcessSet(opt);
            if (c.Builder.SetOpts.Contains(opt)) 
            {
                c.setLateImplSets.Add(opt, impl);
            } 
            else 
            {
                c.setLateImpls.Add(opt, impl);
            }
            return c;
        }

        public ConfigurationModule Set<T, U>(IParam<T> opt, GenericType<U> val) 
            where U : T
        {
            Type t = typeof(U);
            string n = ReflectionUtilities.GetAssemblyQualifiedName(t);
            return Set(opt, n);
        }

        public ConfigurationModule Set(IParam<bool> opt, bool val)
        {
            return Set(opt, val);
        }

        ////TODO
        ////public readonly ConfigurationModule set(Param<? extends Number> opt, Number val) 
        ////{
        ////   return set(opt, val);
        ////}

        public ConfigurationModule Set<T>(IParam<T> opt, string val) 
        {
            ConfigurationModule c = DeepCopy();
            c.ProcessSet(opt);
            if (c.Builder.SetOpts.Contains(opt)) 
            {
                c.setParamSets.Add(opt, val);
            } 
            else 
            {
                c.setParams.Add(opt, val);
            }
            return c;
        }

        public ConfigurationModule Set<T>(IImpl<IList<T>> opt, IList<string> impl)
        {
            ConfigurationModule c = DeepCopy();
            c.ProcessSet(opt);
            c.setLateImplLists.Add(opt, impl);
            return c;
        }

        public ConfigurationModule Set<T>(IParam<IList<T>> opt, IList<string> impl)
        {
            ConfigurationModule c = DeepCopy();
            c.ProcessSet(opt);
            c.setParamLists.Add(opt, impl);
            return c;
        }

        public ConfigurationModule Set<T>(IImpl<IList<T>> opt, IList<Type> impl)
        {
            ConfigurationModule c = DeepCopy();
            c.ProcessSet(opt);
            c.setImplLists.Add(opt, impl);
            return c;
        }

        public IConfiguration Build()
        {
            ConfigurationModule c = DeepCopy();
    
            if (!c.reqSet.ContainsAll(c.Builder.ReqDecl)) 
            {
                ISet<FieldInfo> missingSet = new MonotonicHashSet<FieldInfo>();
                foreach (FieldInfo f in c.Builder.ReqDecl) 
                {
                    if (!c.reqSet.Contains(f)) 
                    {
                        missingSet.Add(f);
                    }
                }
                var e = new BindException(
                    "Attempt to build configuration before setting required option(s): "
                    + Builder.ToString(missingSet));
                Org.Apache.REEF.Utilities.Diagnostics.Exceptions.Throw(e, LOGGER);
            }
  
            foreach (Type clazz in c.Builder.FreeImpls.Keys) 
            {
                object i = c.Builder.FreeImpls.Get(clazz);
                if (c.setImpls.ContainsKey(i))
                {
                    var cb = (ICsInternalConfigurationBuilder)c.Builder.B;
                    cb.Bind(clazz, c.setImpls.Get(i));
                } 
                else if (c.setLateImpls.ContainsKey(i)) 
                {
                    c.Builder.B.Bind(ReflectionUtilities.GetAssemblyQualifiedName(clazz), c.setLateImpls.Get(i));
                } 
                else if (c.setImplSets.ContainsKey(i) || c.setLateImplSets.ContainsKey(i))
                {
                    foreach (Type clz in c.setImplSets.GetValuesForKey(i))
                    {
                        ICsInternalConfigurationBuilder b = (ICsInternalConfigurationBuilder)c.Builder.B;
                        b.BindSetEntry(clazz, clz);
                    }
                    foreach (string s in c.setLateImplSets.GetValuesForKey(i))
                    {
                        ICsInternalConfigurationBuilder b = (ICsInternalConfigurationBuilder)c.Builder.B;
                        b.BindSetEntry(clazz, s);
                    }
                } 
                else if (c.setImplLists.ContainsKey(i))
                {
                    ICsConfigurationBuilder b = (ICsConfigurationBuilder)c.Builder.B;
                    b.BindList(clazz, setImplLists.Get(i));
                }
                else if (c.setLateImplLists.ContainsKey(i))
                {
                    ICsInternalConfigurationBuilder b = (ICsInternalConfigurationBuilder)c.Builder.B;
                    b.BindList(clazz, setLateImplLists.Get(i));
                }
            }
            
            foreach (Type clazz in c.Builder.FreeParams.Keys) 
            {
                object p = c.Builder.FreeParams.Get(clazz);
                string s = c.setParams.Get(p);
                bool foundOne = false;
                if (s != null) 
                {
                    ICsConfigurationBuilder cb = c.Builder.B;
                    cb.BindNamedParameter(clazz, s);
                    foundOne = true;
                }

                IList<string> paramListStr = c.setParamLists.Get(p);
                if (paramListStr != null)
                {
                    ICsInternalConfigurationBuilder b = (ICsInternalConfigurationBuilder)c.Builder.B;
                    b.BindList(clazz, paramListStr);
                    foundOne = true;
                }

                foreach (string paramStr in c.setParamSets.GetValuesForKey(p)) 
                {
                    ICsInternalConfigurationBuilder b = (ICsInternalConfigurationBuilder)c.Builder.B;
                    b.BindSetEntry(clazz, paramStr);   
                    foundOne = true;
                }

                if (!foundOne) 
                {
                    if (!ReflectionUtilities.IsInstanceOfGeneric(p, typeof(OptionalParameter<>)))
                    {
                        Org.Apache.REEF.Utilities.Diagnostics.Exceptions.Throw(new IllegalStateException(), LOGGER);
                    }
                }
            }
            return c.Builder.B.Build();
        }

        public void AssertStaticClean() 
        {
            if (!(
                setImpls.IsEmpty() &&
                setParams.IsEmpty()) &&
                setImplSets.IsEmpty() &&
                setLateImplSets.IsEmpty() &&
                setParamSets.IsEmpty() &&
                setImplLists.IsEmpty() &&
                setLateImplLists.IsEmpty() &&
                setParamLists.IsEmpty() &&
                setLateImpls.IsEmpty())
            {
                var e = new ClassHierarchyException("Detected statically set ConfigurationModule Parameter / Implementation.  set() should only be used dynamically.  Use bind...() instead.");
                Org.Apache.REEF.Utilities.Diagnostics.Exceptions.Throw(e, LOGGER);
            }
        }

        private ConfigurationModule DeepCopy()
        {
            ConfigurationModule cm = new ConfigurationModule(Builder.DeepCopy());
            cm.setImpls.AddAll(setImpls);
            cm.setParams.AddAll(setParams);
            cm.setImplSets.AddAll(setImplSets);
            cm.setParamSets.AddAll(setParamSets);
            cm.setLateImplSets.AddAll(setLateImplSets);
            cm.setImplLists.AddAll(setImplLists);
            cm.setParamLists.AddAll(setParamLists);
            cm.setLateImplLists.AddAll(setLateImplLists);
            cm.setLateImpls.AddAll(setLateImpls);
            cm.reqSet.AddAll(reqSet);
            return cm;
        }

        private void ProcessSet(object impl)
        {
            FieldInfo f;
            Builder.Map.TryGetValue(impl, out f);
            if (f == null)
            { 
                var e = new ClassHierarchyException("Unknown Impl/Param when setting " + impl.GetType().Name + ".  Did you pass in a field from some other module?");
                Org.Apache.REEF.Utilities.Diagnostics.Exceptions.Throw(e, LOGGER);
            }
            if (!reqSet.Contains(f))
            {
                reqSet.Add(f);
            }
        }
    }
}
