/*******************************************************************************
 * Copyright © 2016 WaterCloud.Framework 版权所有
 * Author: WaterCloud
 * Description: WaterCloud快速开发平台
 * Website：
*********************************************************************************/

using System;
using System.Collections;
using System.Collections.Generic;

namespace WaterCloud.Code
{
	public static partial class Extensions
	{
		#region 数值转换

		/// <summary>
		/// 转换为整型
		/// </summary>
		/// <param name="data">数据</param>
		public static int ToInt(this object data)
		{
			if (data == null)
				return 0;
			int result;
			var success = int.TryParse(data.ToString(), out result);
			if (success)
				return result;
			try
			{
				return Convert.ToInt32(ToDouble(data, 0));
			}
			catch (Exception)
			{
				return 0;
			}
		}

		/// <summary>
		/// 将object转换为long，若转换失败，则返回0。不抛出异常。
		/// </summary>
		/// <param name="str"></param>
		/// <returns></returns>
		public static long ToLong(this object obj)
		{
			try
			{
				return long.Parse(obj.ToString());
			}
			catch
			{
				return 0L;
			}
		}

		/// <summary>
		/// 转换为可空整型
		/// </summary>
		/// <param name="data">数据</param>
		public static int? ToIntOrNull(this object data)
		{
			if (data == null)
				return null;
			int result;
			bool isValid = int.TryParse(data.ToString(), out result);
			if (isValid)
				return result;
			return null;
		}

		/// <summary>
		/// 转换为双精度浮点数
		/// </summary>
		/// <param name="data">数据</param>
		public static double ToDouble(this object data)
		{
			if (data == null)
				return 0;
			double result;
			return double.TryParse(data.ToString(), out result) ? result : 0;
		}

		/// <summary>
		/// 转换为双精度浮点数,并按指定的小数位4舍5入
		/// </summary>
		/// <param name="data">数据</param>
		/// <param name="digits">小数位数</param>
		public static double ToDouble(this object data, int digits)
		{
			return Math.Round(ToDouble(data), digits);
		}

		/// <summary>
		/// 转换为可空双精度浮点数
		/// </summary>
		/// <param name="data">数据</param>
		public static double? ToDoubleOrNull(this object data)
		{
			if (data == null)
				return null;
			double result;
			bool isValid = double.TryParse(data.ToString(), out result);
			if (isValid)
				return result;
			return null;
		}

		/// <summary>
		/// 转换为高精度浮点数
		/// </summary>
		/// <param name="data">数据</param>
		public static decimal ToDecimal(this object data)
		{
			if (data == null)
				return 0;
			decimal result;
			return decimal.TryParse(data.ToString(), out result) ? result : 0;
		}

		/// <summary>
		/// 转换为高精度浮点数,并按指定的小数位4舍5入
		/// </summary>
		/// <param name="data">数据</param>
		/// <param name="digits">小数位数</param>
		public static decimal ToDecimal(this object data, int digits)
		{
			return Math.Round(ToDecimal(data), digits);
		}

		/// <summary>
		/// 转换为可空高精度浮点数
		/// </summary>
		/// <param name="data">数据</param>
		public static decimal? ToDecimalOrNull(this object data)
		{
			if (data == null)
				return null;
			decimal result;
			bool isValid = decimal.TryParse(data.ToString(), out result);
			if (isValid)
				return result;
			return null;
		}

		/// <summary>
		/// 转换为可空高精度浮点数,并按指定的小数位4舍5入
		/// </summary>
		/// <param name="data">数据</param>
		/// <param name="digits">小数位数</param>
		public static decimal? ToDecimalOrNull(this object data, int digits)
		{
			var result = ToDecimalOrNull(data);
			if (result == null)
				return null;
			return Math.Round(result.Value, digits);
		}

		#endregion 数值转换

		#region 日期转换

		/// <summary>
		/// 转换为日期
		/// </summary>
		/// <param name="data">数据</param>
		public static DateTime ToDate(this object data)
		{
			if (data == null)
				return DateTime.MinValue;
			DateTime result;
			return DateTime.TryParse(data.ToString(), out result) ? result : DateTime.MinValue;
		}

		/// <summary>
		/// 转换为可空日期
		/// </summary>
		/// <param name="data">数据</param>
		public static DateTime? ToDateOrNull(this object data)
		{
			if (data == null)
				return null;
			DateTime result;
			bool isValid = DateTime.TryParse(data.ToString(), out result);
			if (isValid)
				return result;
			return null;
		}

		#endregion 日期转换

		#region 布尔转换

		/// <summary>
		/// 转换为布尔值
		/// </summary>
		/// <param name="data">数据</param>
		public static bool ToBool(this object data)
		{
			if (data == null)
				return false;
			bool? value = GetBool(data);
			if (value != null)
				return value.Value;
			bool result;
			return bool.TryParse(data.ToString(), out result) && result;
		}

		/// <summary>
		/// 获取布尔值
		/// </summary>
		private static bool? GetBool(this object data)
		{
			switch (data.ToString().Trim().ToLower())
			{
				case "0":
					return false;

				case "1":
					return true;

				case "是":
					return true;

				case "否":
					return false;

				case "yes":
					return true;

				case "no":
					return false;

				default:
					return null;
			}
		}

		/// <summary>
		/// 转换为可空布尔值
		/// </summary>
		/// <param name="data">数据</param>
		public static bool? ToBoolOrNull(this object data)
		{
			if (data == null)
				return null;
			bool? value = GetBool(data);
			if (value != null)
				return value.Value;
			bool result;
			bool isValid = bool.TryParse(data.ToString(), out result);
			if (isValid)
				return result;
			return null;
		}

		#endregion 布尔转换

		#region 是否为空

		/// <summary>
		/// 是否为空
		/// </summary>
		/// <param name="value">值</param>
		public static bool IsEmpty(this string value)
		{
			return string.IsNullOrWhiteSpace(value);
		}

		/// <summary>
		/// 是否为空
		/// </summary>
		/// <param name="value"></param>
		/// <returns></returns>
		public static bool IsEmpty(this object value)
		{
			if (value != null && !string.IsNullOrEmpty(value.ToString()))
			{
				return false;
			}
			else
			{
				return true;
			}
		}

		/// <summary>
		/// 是否为空
		/// </summary>
		/// <param name="value">值</param>
		public static bool IsEmpty(this Guid? value)
		{
			if (value == null)
				return true;
			return IsEmpty(value.Value);
		}

		/// <summary>
		/// 是否为空
		/// </summary>
		/// <param name="value">值</param>
		public static bool IsEmpty(this Guid value)
		{
			if (value == Guid.Empty)
				return true;
			return false;
		}

		#endregion 是否为空

		#region 强制转换类型

		/// <summary>
		/// 强制转换类型
		/// </summary>
		/// <typeparam name="TResult"></typeparam>
		/// <param name="source"></param>
		/// <returns></returns>
		public static IEnumerable<TResult> CastSuper<TResult>(this IEnumerable source)
		{
			foreach (object item in source)
			{
				yield return (TResult)Convert.ChangeType(item, typeof(TResult));
			}
		}

		#endregion 强制转换类型

		#region 转换为long

		/// <summary>
		/// 将object转换为long，若转换失败，则返回0。不抛出异常。
		/// </summary>
		/// <param name="str"></param>
		/// <returns></returns>
		public static long ParseToLong(this object obj)
		{
			try
			{
				return long.Parse(obj.ToString());
			}
			catch
			{
				return 0L;
			}
		}

		/// <summary>
		/// 将object转换为long，若转换失败，则返回指定值。不抛出异常。
		/// </summary>
		/// <param name="str"></param>
		/// <param name="defaultValue"></param>
		/// <returns></returns>
		public static long ParseToLong(this string str, long defaultValue)
		{
			try
			{
				return long.Parse(str);
			}
			catch
			{
				return defaultValue;
			}
		}

		#endregion 转换为long

		#region 转换为int

		/// <summary>
		/// 将object转换为int，若转换失败，则返回0。不抛出异常。
		/// </summary>
		/// <param name="str"></param>
		/// <returns></returns>
		public static int ParseToInt(this object str)
		{
			try
			{
				return Convert.ToInt32(str);
			}
			catch
			{
				return 0;
			}
		}

		/// <summary>
		/// 将object转换为int，若转换失败，则返回指定值。不抛出异常。
		/// null返回默认值
		/// </summary>
		/// <param name="str"></param>
		/// <param name="defaultValue"></param>
		/// <returns></returns>
		public static int ParseToInt(this object str, int defaultValue)
		{
			if (str == null)
			{
				return defaultValue;
			}
			try
			{
				return Convert.ToInt32(str);
			}
			catch
			{
				return defaultValue;
			}
		}

		#endregion 转换为int

		#region 转换为short

		/// <summary>
		/// 将object转换为short，若转换失败，则返回0。不抛出异常。
		/// </summary>
		/// <param name="str"></param>
		/// <returns></returns>
		public static short ParseToShort(this object obj)
		{
			try
			{
				return short.Parse(obj.ToString());
			}
			catch
			{
				return 0;
			}
		}

		/// <summary>
		/// 将object转换为short，若转换失败，则返回指定值。不抛出异常。
		/// </summary>
		/// <param name="str"></param>
		/// <returns></returns>
		public static short ParseToShort(this object str, short defaultValue)
		{
			try
			{
				return short.Parse(str.ToString());
			}
			catch
			{
				return defaultValue;
			}
		}

		#endregion 转换为short

		#region 转换为demical

		/// <summary>
		/// 将object转换为demical，若转换失败，则返回指定值。不抛出异常。
		/// </summary>
		/// <param name="str"></param>
		/// <returns></returns>
		public static decimal ParseToDecimal(this object str, decimal defaultValue)
		{
			try
			{
				return decimal.Parse(str.ToString());
			}
			catch
			{
				return defaultValue;
			}
		}

		/// <summary>
		/// 将object转换为demical，若转换失败，则返回0。不抛出异常。
		/// </summary>
		/// <param name="str"></param>
		/// <returns></returns>
		public static decimal ParseToDecimal(this object str)
		{
			try
			{
				return decimal.Parse(str.ToString());
			}
			catch
			{
				return 0;
			}
		}

		#endregion 转换为demical

		#region 转化为bool

		/// <summary>
		/// 将object转换为bool，若转换失败，则返回false。不抛出异常。
		/// </summary>
		/// <param name="str"></param>
		/// <returns></returns>
		public static bool ParseToBool(this object str)
		{
			try
			{
				return bool.Parse(str.ToString());
			}
			catch
			{
				return false;
			}
		}

		/// <summary>
		/// 将object转换为bool，若转换失败，则返回指定值。不抛出异常。
		/// </summary>
		/// <param name="str"></param>
		/// <returns></returns>
		public static bool ParseToBool(this object str, bool result)
		{
			try
			{
				return bool.Parse(str.ToString());
			}
			catch
			{
				return result;
			}
		}

		#endregion 转化为bool

		#region 转换为float

		/// <summary>
		/// 将object转换为float，若转换失败，则返回0。不抛出异常。
		/// </summary>
		/// <param name="str"></param>
		/// <returns></returns>
		public static float ParseToFloat(this object str)
		{
			try
			{
				return float.Parse(str.ToString());
			}
			catch
			{
				return 0;
			}
		}

		/// <summary>
		/// 将object转换为float，若转换失败，则返回指定值。不抛出异常。
		/// </summary>
		/// <param name="str"></param>
		/// <returns></returns>
		public static float ParseToFloat(this object str, float result)
		{
			try
			{
				return float.Parse(str.ToString());
			}
			catch
			{
				return result;
			}
		}

		#endregion 转换为float

		#region 转换为Guid

		/// <summary>
		/// 将string转换为Guid，若转换失败，则返回Guid.Empty。不抛出异常。
		/// </summary>
		/// <param name="str"></param>
		/// <returns></returns>
		public static Guid ParseToGuid(this string str)
		{
			try
			{
				return new Guid(str);
			}
			catch
			{
				return Guid.Empty;
			}
		}

		#endregion 转换为Guid

		#region 转换为DateTime

		/// <summary>
		/// 将string转换为DateTime，若转换失败，则返回日期最小值。不抛出异常。
		/// </summary>
		/// <param name="str"></param>
		/// <returns></returns>
		public static DateTime ParseToDateTime(this string str)
		{
			try
			{
				if (string.IsNullOrWhiteSpace(str))
				{
					return DateTime.MinValue;
				}
				if (str.Contains("-") || str.Contains("/"))
				{
					return DateTime.Parse(str);
				}
				else
				{
					int length = str.Length;
					switch (length)
					{
						case 4:
							return DateTime.ParseExact(str, "yyyy", System.Globalization.CultureInfo.CurrentCulture);

						case 6:
							return DateTime.ParseExact(str, "yyyyMM", System.Globalization.CultureInfo.CurrentCulture);

						case 8:
							return DateTime.ParseExact(str, "yyyyMMdd", System.Globalization.CultureInfo.CurrentCulture);

						case 10:
							return DateTime.ParseExact(str, "yyyyMMddHH", System.Globalization.CultureInfo.CurrentCulture);

						case 12:
							return DateTime.ParseExact(str, "yyyyMMddHHmm", System.Globalization.CultureInfo.CurrentCulture);

						case 14:
							return DateTime.ParseExact(str, "yyyyMMddHHmmss", System.Globalization.CultureInfo.CurrentCulture);

						default:
							return DateTime.ParseExact(str, "yyyyMMddHHmmss", System.Globalization.CultureInfo.CurrentCulture);
					}
				}
			}
			catch
			{
				return DateTime.MinValue;
			}
		}

		/// <summary>
		/// 将string转换为DateTime，若转换失败，则返回默认值。
		/// </summary>
		/// <param name="str"></param>
		/// <param name="defaultValue"></param>
		/// <returns></returns>
		public static DateTime ParseToDateTime(this string str, DateTime? defaultValue)
		{
			try
			{
				if (string.IsNullOrWhiteSpace(str))
				{
					return defaultValue.GetValueOrDefault();
				}
				if (str.Contains("-") || str.Contains("/"))
				{
					return DateTime.Parse(str);
				}
				else
				{
					int length = str.Length;
					switch (length)
					{
						case 4:
							return DateTime.ParseExact(str, "yyyy", System.Globalization.CultureInfo.CurrentCulture);

						case 6:
							return DateTime.ParseExact(str, "yyyyMM", System.Globalization.CultureInfo.CurrentCulture);

						case 8:
							return DateTime.ParseExact(str, "yyyyMMdd", System.Globalization.CultureInfo.CurrentCulture);

						case 10:
							return DateTime.ParseExact(str, "yyyyMMddHH", System.Globalization.CultureInfo.CurrentCulture);

						case 12:
							return DateTime.ParseExact(str, "yyyyMMddHHmm", System.Globalization.CultureInfo.CurrentCulture);

						case 14:
							return DateTime.ParseExact(str, "yyyyMMddHHmmss", System.Globalization.CultureInfo.CurrentCulture);

						default:
							return DateTime.ParseExact(str, "yyyyMMddHHmmss", System.Globalization.CultureInfo.CurrentCulture);
					}
				}
			}
			catch
			{
				return defaultValue.GetValueOrDefault();
			}
		}

		#endregion 转换为DateTime

		#region 转换为string

		/// <summary>
		/// 将object转换为string，若转换失败，则返回""。不抛出异常。
		/// </summary>
		/// <param name="str"></param>
		/// <returns></returns>
		public static string ParseToString(this object obj)
		{
			try
			{
				if (obj == null)
				{
					return string.Empty;
				}
				else
				{
					return obj.ToString();
				}
			}
			catch
			{
				return string.Empty;
			}
		}

		public static string ParseToStrings<T>(this object obj)
		{
			try
			{
				var list = obj as IEnumerable<T>;
				if (list != null)
				{
					return string.Join(",", list);
				}
				else
				{
					return obj.ToString();
				}
			}
			catch
			{
				return string.Empty;
			}
		}

		#endregion 转换为string

		#region 转换为double

		/// <summary>
		/// 将object转换为double，若转换失败，则返回0。不抛出异常。
		/// </summary>
		/// <param name="obj"></param>
		/// <returns></returns>
		public static double ParseToDouble(this object obj)
		{
			try
			{
				return double.Parse(obj.ToString());
			}
			catch
			{
				return 0;
			}
		}

		/// <summary>
		/// 将object转换为double，若转换失败，则返回指定值。不抛出异常。
		/// </summary>
		/// <param name="str"></param>
		/// <param name="defaultValue"></param>
		/// <returns></returns>
		public static double ParseToDouble(this object str, double defaultValue)
		{
			try
			{
				return double.Parse(str.ToString());
			}
			catch
			{
				return defaultValue;
			}
		}

		#endregion 转换为double

		/// <summary>
		/// 安全返回值
		/// </summary>
		/// <param name="value">可空值</param>
		public static T SafeValue<T>(this T? value) where T : struct
		{
			return value ?? default(T);
		}
	}
}