#region Apache License
//
// 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.
//
#endregion

using System;
using System.Collections;
using System.Globalization;
using System.Reflection;
using System.Text;

using log4net.Core;
using log4net.Util.TypeConverters;

namespace log4net.Util
{
	/// <summary>
	/// A convenience class to convert property values to specific types.
	/// </summary>
	/// <remarks>
	/// <para>
	/// Utility functions for converting types and parsing values.
	/// </para>
	/// </remarks>
	/// <author>Nicko Cadell</author>
	/// <author>Gert Driesen</author>
	public sealed class OptionConverter
	{
		#region Private Instance Constructors

		/// <summary>
		/// Initializes a new instance of the <see cref="OptionConverter" /> class.
		/// </summary>
		/// <remarks>
		/// <para>
		/// Uses a private access modifier to prevent instantiation of this class.
		/// </para>
		/// </remarks>
		private OptionConverter()
		{
		}

		#endregion Private Instance Constructors

		#region Public Static Methods

//		/// <summary>
//		/// Concatenates two string arrays.
//		/// </summary>
//		/// <param name="l">Left array.</param>
//		/// <param name="r">Right array.</param>
//		/// <returns>Array containing both left and right arrays.</returns>
//		public static string[] ConcatenateArrays(string[] l, string[] r)
//		{
//			return (string[])ConcatenateArrays(l, r);
//		}

//		/// <summary>
//		/// Concatenates two arrays.
//		/// </summary>
//		/// <param name="l">Left array</param>
//		/// <param name="r">Right array</param>
//		/// <returns>Array containing both left and right arrays.</returns>
//		public static Array ConcatenateArrays(Array l, Array r)
//		{
//			if (l == null)
//			{
//				throw new ArgumentNullException("l");
//			}
//			if (r == null)
//			{
//				throw new ArgumentNullException("r");
//			}
//
//			int len = l.Length + r.Length;
//			Array a = Array.CreateInstance(l.GetType(), len);
//
//			Array.Copy(l, 0, a, 0, l.Length);
//			Array.Copy(r, 0, a, l.Length, r.Length);
//
//			return a;
//		}

//		/// <summary>
//		/// Converts string escape characters back to their correct values.
//		/// </summary>
//		/// <param name="s">String to convert.</param>
//		/// <returns>Converted result.</returns>
//		public static string ConvertSpecialChars(string s)
//		{
//			if (s == null)
//			{
//				throw new ArgumentNullException("s");
//			}
//			char c;
//			int len = s.Length;
//			StringBuilder buf = new StringBuilder(len);
//
//			int i = 0;
//			while(i < len)
//			{
//				c = s[i++];
//				if (c == '\\')
//				{
//					c =  s[i++];
//					if (c == 'n')	  c = '\n';
//					else if (c == 'r') c = '\r';
//					else if (c == 't') c = '\t';
//					else if (c == 'f') c = '\f';
//					else if (c == '\b') c = '\b';
//					else if (c == '\"') c = '\"';
//					else if (c == '\'') c = '\'';
//					else if (c == '\\') c = '\\';
//				}
//				buf.Append(c);
//			}
//			return buf.ToString();
//		}

		/// <summary>
		/// Converts a string to a <see cref="bool" /> value.
		/// </summary>
		/// <param name="argValue">String to convert.</param>
		/// <param name="defaultValue">The default value.</param>
		/// <returns>The <see cref="bool" /> value of <paramref name="argValue" />.</returns>
		/// <remarks>
		/// <para>
		/// If <paramref name="argValue"/> is "true", then <c>true</c> is returned.
		/// If <paramref name="argValue"/> is "false", then <c>false</c> is returned.
		/// Otherwise, <paramref name="defaultValue"/> is returned.
		/// </para>
		/// </remarks>
		public static bool ToBoolean(string argValue, bool defaultValue)
		{
			if (argValue != null && argValue.Length > 0)
			{
				try
				{
					return bool.Parse(argValue);
				}
				catch(Exception e)
				{
					LogLog.Error(declaringType, "[" + argValue + "] is not in proper bool form.", e);
				}
			}
			return defaultValue;
		}

//		/// <summary>
//		/// Converts a string to an integer.
//		/// </summary>
//		/// <param name="argValue">String to convert.</param>
//		/// <param name="defaultValue">The default value.</param>
//		/// <returns>The <see cref="int" /> value of <paramref name="argValue" />.</returns>
//		/// <remarks>
//		/// <para>
//		/// <paramref name="defaultValue"/> is returned when <paramref name="argValue"/>
//		/// cannot be converted to a <see cref="int" /> value.
//		/// </para>
//		/// </remarks>
//		public static int ToInt(string argValue, int defaultValue)
//		{
//			if (argValue != null)
//			{
//				string s = argValue.Trim();
//				try
//				{
//					return int.Parse(s, NumberFormatInfo.InvariantInfo);
//				}
//				catch (Exception e)
//				{
//					LogLog.Error(declaringType, "OptionConverter: [" + s + "] is not in proper int form.", e);
//				}
//			}
//			return defaultValue;
//		}

		/// <summary>
		/// Parses a file size into a number.
		/// </summary>
		/// <param name="argValue">String to parse.</param>
		/// <param name="defaultValue">The default value.</param>
		/// <returns>The <see cref="long" /> value of <paramref name="argValue" />.</returns>
		/// <remarks>
		/// <para>
		/// Parses a file size of the form: number[KB|MB|GB] into a
		/// long value. It is scaled with the appropriate multiplier.
		/// </para>
		/// <para>
		/// <paramref name="defaultValue"/> is returned when <paramref name="argValue"/>
		/// cannot be converted to a <see cref="long" /> value.
		/// </para>
		/// </remarks>
		public static long ToFileSize(string argValue, long defaultValue)
		{
			if (argValue == null)
			{
				return defaultValue;
			}

			string s = argValue.Trim().ToUpper(CultureInfo.InvariantCulture);
			long multiplier = 1;
			int index;

			if ((index = s.IndexOf("KB")) != -1)
			{
				multiplier = 1024;
				s = s.Substring(0, index);
			}
			else if ((index = s.IndexOf("MB")) != -1)
			{
				multiplier = 1024 * 1024;
				s = s.Substring(0, index);
			}
			else if ((index = s.IndexOf("GB")) != -1)
			{
				multiplier = 1024 * 1024 * 1024;
				s = s.Substring(0, index);
			}
			if (s != null)
			{
				// Try again to remove whitespace between the number and the size specifier
				s = s.Trim();

				long longVal;
				if (SystemInfo.TryParse(s, out longVal))
				{
					return longVal * multiplier;
				}
				else
				{
					LogLog.Error(declaringType, "OptionConverter: ["+ s +"] is not in the correct file size syntax.");
				}
			}
			return defaultValue;
		}

		/// <summary>
		/// Converts a string to an object.
		/// </summary>
		/// <param name="target">The target type to convert to.</param>
		/// <param name="txt">The string to convert to an object.</param>
		/// <returns>
		/// The object converted from a string or <c>null</c> when the
		/// conversion failed.
		/// </returns>
		/// <remarks>
		/// <para>
		/// Converts a string to an object. Uses the converter registry to try
		/// to convert the string value into the specified target type.
		/// </para>
		/// </remarks>
		public static object ConvertStringTo(Type target, string txt)
		{
			if (target == null)
			{
				throw new ArgumentNullException("target");
			}

			// If we want a string we already have the correct type
			if (typeof(string) == target || typeof(object) == target)
			{
				return txt;
			}

			// First lets try to find a type converter
			IConvertFrom typeConverter = ConverterRegistry.GetConvertFrom(target);
			if (typeConverter != null && typeConverter.CanConvertFrom(typeof(string)))
			{
				// Found appropriate converter
				return typeConverter.ConvertFrom(txt);
			}
			else
			{
#if NETSTANDARD1_3
				if (target.GetTypeInfo().IsEnum)
#else
				if (target.IsEnum)
#endif
				{
					// Target type is an enum.

					// Use the Enum.Parse(EnumType, string) method to get the enum value
					return ParseEnum(target, txt, true);
				}
				else
				{
					// We essentially make a guess that to convert from a string
					// to an arbitrary type T there will be a static method defined on type T called Parse
					// that will take an argument of type string. i.e. T.Parse(string)->T we call this
					// method to convert the string to the type required by the property.
					System.Reflection.MethodInfo meth = target.GetMethod("Parse", new Type[] {typeof(string)});
					if (meth != null)
					{
						// Call the Parse method
#if NETSTANDARD1_3
						return meth.Invoke(target, new[] { txt });
#else
						return meth.Invoke(null, BindingFlags.InvokeMethod, null, new object[] {txt}, CultureInfo.InvariantCulture);
#endif
					}
					else
					{
						// No Parse() method found.
					}
				}
			}
			return null;
		}

//		/// <summary>
//		/// Looks up the <see cref="IConvertFrom"/> for the target type.
//		/// </summary>
//		/// <param name="target">The type to lookup the converter for.</param>
//		/// <returns>The converter for the specified type.</returns>
//		public static IConvertFrom GetTypeConverter(Type target)
//		{
//			IConvertFrom converter = ConverterRegistry.GetConverter(target);
//			if (converter == null)
//			{
//				throw new InvalidOperationException("No type converter defined for [" + target + "]");
//			}
//			return converter;
//		}

		/// <summary>
		/// Checks if there is an appropriate type conversion from the source type to the target type.
		/// </summary>
		/// <param name="sourceType">The type to convert from.</param>
		/// <param name="targetType">The type to convert to.</param>
		/// <returns><c>true</c> if there is a conversion from the source type to the target type.</returns>
		/// <remarks>
		/// Checks if there is an appropriate type conversion from the source type to the target type.
		/// <para>
		/// </para>
		/// </remarks>
		public static bool CanConvertTypeTo(Type sourceType, Type targetType)
		{
			if (sourceType == null || targetType == null)
			{
				return false;
			}

			// Check if we can assign directly from the source type to the target type
			if (targetType.IsAssignableFrom(sourceType))
			{
				return true;
			}

			// Look for a To converter
			IConvertTo tcSource = ConverterRegistry.GetConvertTo(sourceType, targetType);
			if (tcSource != null)
			{
				if (tcSource.CanConvertTo(targetType))
				{
					return true;
				}
			}

			// Look for a From converter
			IConvertFrom tcTarget = ConverterRegistry.GetConvertFrom(targetType);
			if (tcTarget != null)
			{
				if (tcTarget.CanConvertFrom(sourceType))
				{
					return true;
				}
			}

			return false;
		}

		/// <summary>
		/// Converts an object to the target type.
		/// </summary>
		/// <param name="sourceInstance">The object to convert to the target type.</param>
		/// <param name="targetType">The type to convert to.</param>
		/// <returns>The converted object.</returns>
		/// <remarks>
		/// <para>
		/// Converts an object to the target type.
		/// </para>
		/// </remarks>
		public static object ConvertTypeTo(object sourceInstance, Type targetType)
		{
			Type sourceType = sourceInstance.GetType();

			// Check if we can assign directly from the source type to the target type
			if (targetType.IsAssignableFrom(sourceType))
			{
				return sourceInstance;
			}

			// Look for a TO converter
			IConvertTo tcSource = ConverterRegistry.GetConvertTo(sourceType, targetType);
			if (tcSource != null)
			{
				if (tcSource.CanConvertTo(targetType))
				{
					return tcSource.ConvertTo(sourceInstance, targetType);
				}
			}

			// Look for a FROM converter
			IConvertFrom tcTarget = ConverterRegistry.GetConvertFrom(targetType);
			if (tcTarget != null)
			{
				if (tcTarget.CanConvertFrom(sourceType))
				{
					return tcTarget.ConvertFrom(sourceInstance);
				}
			}

			throw new ArgumentException("Cannot convert source object [" + sourceInstance.ToString() + "] to target type [" + targetType.Name + "]", "sourceInstance");
		}

//		/// <summary>
//		/// Finds the value corresponding to <paramref name="key"/> in
//		/// <paramref name="props"/> and then perform variable substitution
//		/// on the found value.
//		/// </summary>
//		/// <param name="key">The key to lookup.</param>
//		/// <param name="props">The association to use for lookups.</param>
//		/// <returns>The substituted result.</returns>
//		public static string FindAndSubst(string key, System.Collections.IDictionary props)
//		{
//			if (props == null)
//			{
//				throw new ArgumentNullException("props");
//			}
//
//			string v = props[key] as string;
//			if (v == null)
//			{
//				return null;
//			}
//
//			try
//			{
//				return SubstituteVariables(v, props);
//			}
//			catch(Exception e)
//			{
//				LogLog.Error(declaringType, "OptionConverter: Bad option value [" + v + "].", e);
//				return v;
//			}
//		}

		/// <summary>
		/// Instantiates an object given a class name.
		/// </summary>
		/// <param name="className">The fully qualified class name of the object to instantiate.</param>
		/// <param name="superClass">The class to which the new object should belong.</param>
		/// <param name="defaultValue">The object to return in case of non-fulfillment.</param>
		/// <returns>
		/// An instance of the <paramref name="className"/> or <paramref name="defaultValue"/>
		/// if the object could not be instantiated.
		/// </returns>
		/// <remarks>
		/// <para>
		/// Checks that the <paramref name="className"/> is a subclass of
		/// <paramref name="superClass"/>. If that test fails or the object could
		/// not be instantiated, then <paramref name="defaultValue"/> is returned.
		/// </para>
		/// </remarks>
		public static object InstantiateByClassName(string className, Type superClass, object defaultValue)
		{
			if (className != null)
			{
				try
				{
#if NETSTANDARD1_3
					Type classObj = SystemInfo.GetTypeFromString(superClass.GetTypeInfo().Assembly, className, true, true);
#else
					Type classObj = SystemInfo.GetTypeFromString(className, true, true);
#endif
					if (!superClass.IsAssignableFrom(classObj))
					{
						LogLog.Error(declaringType, "OptionConverter: A [" + className + "] object is not assignable to a [" + superClass.FullName + "] variable.");
						return defaultValue;
					}
					return Activator.CreateInstance(classObj);
				}
				catch (Exception e)
				{
					LogLog.Error(declaringType, "Could not instantiate class [" + className + "].", e);
				}
			}
			return defaultValue;
		}

		/// <summary>
		/// Performs variable substitution in string <paramref name="value"/> from the
		/// values of keys found in <paramref name="props"/>.
		/// </summary>
		/// <param name="value">The string on which variable substitution is performed.</param>
		/// <param name="props">The dictionary to use to lookup variables.</param>
		/// <returns>The result of the substitutions.</returns>
		/// <remarks>
		/// <para>
		/// The variable substitution delimiters are <b>${</b> and <b>}</b>.
		/// </para>
		/// <para>
		/// For example, if props contains <c>key=value</c>, then the call
		/// </para>
		/// <para>
		/// <code lang="C#">
		/// string s = OptionConverter.SubstituteVariables("Value of key is ${key}.");
		/// </code>
		/// </para>
		/// <para>
		/// will set the variable <c>s</c> to "Value of key is value.".
		/// </para>
		/// <para>
		/// If no value could be found for the specified key, then substitution
		/// defaults to an empty string.
		/// </para>
		/// <para>
		/// For example, if system properties contains no value for the key
		/// "nonExistentKey", then the call
		/// </para>
		/// <para>
		/// <code lang="C#">
		/// string s = OptionConverter.SubstituteVariables("Value of nonExistentKey is [${nonExistentKey}]");
		/// </code>
		/// </para>
		/// <para>
		/// will set <s>s</s> to "Value of nonExistentKey is []".
		/// </para>
		/// <para>
		/// An Exception is thrown if <paramref name="value"/> contains a start
		/// delimiter "${" which is not balanced by a stop delimiter "}".
		/// </para>
		/// </remarks>
		public static string SubstituteVariables(string value, System.Collections.IDictionary props)
		{
			StringBuilder buf = new StringBuilder();

			int i = 0;
			int j, k;

			while(true)
			{
				j = value.IndexOf(DELIM_START, i);
				if (j == -1)
				{
					if (i == 0)
					{
						return value;
					}
					else
					{
						buf.Append(value.Substring(i, value.Length - i));
						return buf.ToString();
					}
				}
				else
				{
					buf.Append(value.Substring(i, j - i));
					k = value.IndexOf(DELIM_STOP, j);
					if (k == -1)
					{
						throw new LogException("[" + value + "] has no closing brace. Opening brace at position [" + j + "]");
					}
					else
					{
						j += DELIM_START_LEN;
						string key = value.Substring(j, k - j);

						string replacement = props[key] as string;

						if (replacement != null)
						{
							buf.Append(replacement);
						}
						i = k + DELIM_STOP_LEN;
					}
				}
			}
		}

		#endregion Public Static Methods

		#region Private Static Methods

		/// <summary>
		/// Converts the string representation of the name or numeric value of one or
		/// more enumerated constants to an equivalent enumerated object.
		/// </summary>
		/// <param name="enumType">The type to convert to.</param>
		/// <param name="value">The enum string value.</param>
		/// <param name="ignoreCase">If <c>true</c>, ignore case; otherwise, regard case.</param>
		/// <returns>An object of type <paramref name="enumType" /> whose value is represented by <paramref name="value" />.</returns>
		private static object ParseEnum(System.Type enumType, string value, bool ignoreCase)
		{
#if !NETCF
			return Enum.Parse(enumType, value, ignoreCase);
#else
			FieldInfo[] fields = enumType.GetFields(BindingFlags.Public | BindingFlags.Static);

			string[] names = value.Split(new char[] {','});
			for (int i = 0; i < names.Length; ++i)
			{
				names[i] = names [i].Trim();
			}

			long retVal = 0;

			try
			{
				// Attempt to convert to numeric type
				return Enum.ToObject(enumType, Convert.ChangeType(value, typeof(long), CultureInfo.InvariantCulture));
			}
			catch {}

			foreach (string name in names)
			{
				bool found = false;
				foreach(FieldInfo field in fields)
				{
					if (String.Compare(name, field.Name, ignoreCase) == 0)
					{
						retVal |= ((IConvertible) field.GetValue(null)).ToInt64(CultureInfo.InvariantCulture);
						found = true;
						break;
					}
				}
				if (!found)
				{
					throw new ArgumentException("Failed to lookup member [" + name + "] from Enum type [" + enumType.Name + "]");
				}
			}
			return Enum.ToObject(enumType, retVal);
#endif
		}

		#endregion Private Static Methods

		#region Private Static Fields

		/// <summary>
		/// The fully qualified type of the OptionConverter class.
		/// </summary>
		/// <remarks>
		/// Used by the internal logger to record the Type of the
		/// log message.
		/// </remarks>
		private readonly static Type declaringType = typeof(OptionConverter);

		private const string DELIM_START = "${";
		private const char   DELIM_STOP  = '}';
		private const int DELIM_START_LEN = 2;
		private const int DELIM_STOP_LEN  = 1;

		#endregion Private Static Fields
	}
}
