﻿/*
 * 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.Reflection;
using System.Globalization;
using System.Collections.Generic;
using System.Collections.Specialized;
using Apache.NMS;
using Apache.NMS.Util;

namespace Apache.NMS.XMS.Util
{
	/// <summary>
	/// Utility class used to provide convenience methods that apply named
	/// property settings to objects.
	/// </summary>
	public class IntrospectionSupport
	{
        #region Manage maps of member names and URI aliases

		private static Dictionary<Type, StringDictionary> nameMaps =
			new Dictionary<Type, StringDictionary>();
		private static readonly object nameMapsLock = new object();

		/// <summary>
		/// Gets the member names map for the specified type.
		/// </summary>
		/// <param name="type">Type whose names map is requested.</param>
		/// <returns>Names map for the specified type.</returns>
        /// <remarks>
		/// The map is created and registered if it is not found in the
		/// <c>nameMaps</c> registry.
        /// </remarks>
		public static StringDictionary GetNameMap(Type type)
		{
			StringDictionary nameMap;
			lock(IntrospectionSupport.nameMapsLock)
			{
				if(!IntrospectionSupport.nameMaps.TryGetValue(
					type, out nameMap))
				{
					nameMap = CreateNameMap(type);
					IntrospectionSupport.nameMaps.Add(type, nameMap);
				}
			}
			return nameMap;
		}

		/// <summary>
		/// Creates a dictionary of public property and attribute names,
        /// indexed by themselves plus all URI attribute keys associated
		/// to them.
		/// </summary>
		/// <param name="type">Type whose names map is requested.</param>
		/// <returns>Names map for the specified type.</returns>
		/// <remarks>
		/// Applied to this property:
		/// <code>
		///   [UriAttribute("My.Test", "MyTest")]
		///   public string Test
		///   { get { return(_test); }
		///     set { _test = value; }
		///   }
		/// </code>
		/// the method returns a dictionary containing
		/// ("test" -> "Test"), ("my.test" -> "Test"), ("mytest" -> "Test").
		/// Note that <c>StringDictionary</c> converts keys to lowercase but
		/// keeps values untouched.
		/// </remarks>
		public static StringDictionary CreateNameMap(Type type)
		{
			StringDictionary nameMap = new StringDictionary();
			BindingFlags flags = BindingFlags.FlattenHierarchy
							| BindingFlags.Public
							| BindingFlags.Instance;

			// Process public instance self or inherited property
			foreach(PropertyInfo propertyInfo in type.GetProperties(flags))
		    {
				AddToNameMap(nameMap, propertyInfo);
			}

			// Process public instance self or inherited fields
			foreach(FieldInfo fieldInfo in type.GetFields(flags))
		    {
				AddToNameMap(nameMap, fieldInfo);
			}

			return(nameMap);
		}

		/// <summary>
		/// Adds a property or field name and URI attribute keys to the
		/// specified name map.
		/// </summary>
		/// <param name="nameMap">Name map.</param>
		/// <param name="memberInfo">Member information for the property
		/// or field.</param>
		private static void AddToNameMap(StringDictionary nameMap,
			MemberInfo memberInfo)
		{
			// Add member name mapped to itself
			nameMap.Add(memberInfo.Name, memberInfo.Name);

			// For each UriAttribute custom attribute
			foreach(Attribute attr in memberInfo.GetCustomAttributes(
				typeof(UriAttributeAttribute), true))
			{
				// For each URI attribute key
				foreach(string key in
					((UriAttributeAttribute)attr).AttributeKeys)
				{
					// Index property name by URI attribute key
					if(!nameMap.ContainsKey(key))
					{
						nameMap.Add(key, memberInfo.Name);
					}
				}
			}

			return;
		}

        #endregion

		#region Set properties

		/// <summary>
		/// Sets the public properties of a target object using a string map.
		/// This method uses .Net reflection to identify public properties of
		/// the target object matching the keys from the passed map.
		/// </summary>
		/// <param name="target">Object whose properties will be set.</param>
		/// <param name="valueMap">Map of key/value pairs.</param>
		public static void SetProperties(object target,
			StringDictionary valueMap)
		{
			SetProperties(target, valueMap, GetNameMap(target.GetType()));
		}

        /// <summary>
        /// Sets the public properties of a target object using a string map.
        /// This method uses .Net reflection to access public properties of
        /// the target object matching the keys from the passed map.
        /// </summary>
        /// <param name="target">The object whose properties will be set.</param>
        /// <param name="valueMap">Map of key/value pairs.</param>
        /// <param name="nameMap">Map of key/property name pairs.</param>
        public static void SetProperties(object target,
            StringDictionary valueMap,
			StringDictionary nameMap)
        {
			Tracer.DebugFormat("SetProperties called with target: {0}",
				target.GetType().Name);

			// Application of specified values is recursive. If a key does not
			// correspond to a member of the current target object, it is
			// supposed to refer to a sub-member of such a member. Since member
			// keys can contain dot characters, an attempt is made to find the
			// "longest" key corresponding to a member of the current object
			// (this identifies the "sub-target"), and extract the remaining
			// key characters as a sub-key to sub-members.
			// The following dictionary indexes keys to "sub-targets", and
			// "sub-key"/value pairs to assign to "sub-targets".
			Dictionary<string, StringDictionary> subTargetMap = null;

			foreach(string key in valueMap.Keys)
			{
				if(nameMap.ContainsKey(key))
				{
					// Key refers to a member of the current target
					string memberName = nameMap[key];
					MemberInfo member = FindMemberInfo(target, memberName);
					if(member == null)
					{
						// Should not happen if the nameMap was indeed created
						// for the current target object...
						throw new NMSException(string.Format(
							"No such property or field: {0} on class: {1}",
							memberName, target.GetType().Name));
					}

					// Set value
					try
					{
						if(member.MemberType == MemberTypes.Property)
						{
							PropertyInfo property = (PropertyInfo)member;
							object value = ConvertValue(valueMap[key],
								property.PropertyType);
							property.SetValue(target, value, null);
						}
						else
						{
							FieldInfo field = (FieldInfo)member;
							object value = ConvertValue(valueMap[key],
								field.FieldType);
							field.SetValue(target, value);
						}
					}
					catch(Exception ex)
					{
						throw NMSExceptionSupport.Create(
							"Error while attempting to apply option.", ex);
					}
                }
				else
				{
					// Key does NOT refers to a member of the current target
					// Extract maximal member key + subkeys
					string memberKey = key;
					int dotPos = memberKey.LastIndexOf('.');
					bool memberFound = false;
					while(!memberFound && dotPos > 0)
					{
						memberKey = memberKey.Substring(0, dotPos);
						if(nameMap.ContainsKey(memberKey))
						{
							memberKey = nameMap[memberKey];
							memberFound = true;
						}
						else
						{
							dotPos = memberKey.LastIndexOf('.');
						}
					}

					if(!memberFound)
					{
						throw new NMSException(string.Format(
							"Unknown property or field: {0} on class: {1}",
							key, target.GetType().Name));
					}

					// Register memberKey, subKey and value for further processing
					string subKey = key.Substring(dotPos + 1);
					StringDictionary subValueMap;

					if(subTargetMap == null)
					{
						subTargetMap = new Dictionary<string, StringDictionary>();
					}

					if(!subTargetMap.TryGetValue(memberKey, out subValueMap))
					{
						subValueMap = new StringDictionary();
						subTargetMap.Add(memberKey, subValueMap);
					}

					// In theory, we can't have the same subkey twice, since
					// they were unique subkeys from another dictionary.
					// Therefore, no need to check for subValueMap.ContainsKey.
					subValueMap.Add(subKey, valueMap[key]);
				}
            }

			// Now process any compound assignments.
			if(subTargetMap != null)
			{
				foreach(string subTargetKey in subTargetMap.Keys)
				{
					MemberInfo member = FindMemberInfo(target, subTargetKey);
					object subTarget = GetUnderlyingObject(member, target);
					SetProperties(subTarget, subTargetMap[subTargetKey]);
				}
			}
        }

		/// <summary>
		/// Converts the specified string value to the type of the target
		/// member.
		/// </summary>
		private static object ConvertValue(string inputString, Type targetType)
		{
			// If the target member is an enumeration, get the enumeration
			// value or combined (or-ed) values
			object value;
			if(targetType.IsEnum)
			{
				if(inputString.Contains("+"))
				{
					string[] inputValues = inputString.Split('+');

					FieldInfo fieldInfo = targetType.GetField(inputValues[0],
						BindingFlags.Public
						| BindingFlags.Static
						| BindingFlags.IgnoreCase);
					if(fieldInfo == null)
					{
						throw new NMSException(string.Format(
							"Invalid {0} value \"{1}\"", targetType.Name,
							inputValues[0]));
					}
					dynamic val = fieldInfo.GetValue(null);

					for(int v = 1; v < inputValues.Length; v++)
					{
						fieldInfo = targetType.GetField(inputValues[v],
							BindingFlags.Public
							| BindingFlags.Static
							| BindingFlags.IgnoreCase);
						if(fieldInfo == null)
						{
							throw new NMSException(string.Format(
								"Invalid {0} value \"{1}\"", targetType.Name,
								inputValues[v]));
						}
						val = (dynamic)val | (dynamic)fieldInfo.GetValue(null);
					}

					value = Convert.ChangeType(val, targetType);
				}
				else
				{
					FieldInfo fieldInfo = targetType.GetField(inputString,
                                 BindingFlags.Public
                               | BindingFlags.Static
                               | BindingFlags.IgnoreCase);
					if(fieldInfo == null)
					{
						throw new NMSException(string.Format(
							"Invalid {0} value \"{1}\"", targetType.Name,
							inputString));
					}
					value = fieldInfo.GetValue(null);
				}
			}
			else
			{
				// Not an enumeration
				value = Convert.ChangeType(inputString,
					targetType, CultureInfo.InvariantCulture);
			}
			return value;
		}

		#endregion

		#region Get member information and objects

		/// <summary>
		/// Gets member information for a property or field of the target
		/// object.
		///	</summary>
		/// <param name="target">Target object.</param>
		/// <param name="name">Property or field name.</param>
		/// <returns>Retrieved member information.</returns>
        private static MemberInfo FindMemberInfo(object target, string name)
        {
            BindingFlags flags = BindingFlags.FlattenHierarchy
                               | BindingFlags.Public
                               | BindingFlags.Instance
                               | BindingFlags.IgnoreCase;

            Type type = target.GetType();

            MemberInfo member = type.GetProperty(name, flags);

            if(member == null)
            {
                member = type.GetField(name, flags);
            }

            return member;
        }

		/// <summary>
		/// Gets object assigned to the specified property or field member of
		/// the target object.
		///	</summary>
		/// <param name="member">Member information.</param>
		/// <param name="target">Target object.</param>
		/// <returns>Retrieved object.</returns>
		private static object GetUnderlyingObject(
			MemberInfo member, object target)
		{
			object result = null;

			if(member.MemberType == MemberTypes.Field)
			{
				FieldInfo field = member as FieldInfo;

				if(field.FieldType.IsPrimitive)
				{
					throw new NMSException(string.Format(
						"The field given is a primitive type: {0}",
						member.Name));
				}

				result = field.GetValue(target);
			}
			else
			{
				PropertyInfo property = member as PropertyInfo;
				MethodInfo getter = property.GetGetMethod();

				if(getter == null)
				{
					throw new NMSException(string.Format(
						"Cannot access member: {0}",
						member.Name));
				}

				result = getter.Invoke(target, null);
			}

			if(result == null)
			{
				throw new NMSException(string.Format(
					"Could not retrieve the value of member {0}.",
					member.Name));
			}

			return result;
		}

		#endregion
    }
}
