//------------------------------------------------------------------------------
// <copyright file=”*.cs” company=”EhLib Team”>
//     Copyright (c) 2017 Dmitry V. Bolshakov   
// </copyright>
//------------------------------------------------------------------------------

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace EhLib
{

  public enum TypeCategory
  {
    String, Number, DateTime, Boolean, Binary, BinaryImage, Unknown
  }

  public class EhLibManager
  {
    #region private static
    private static EhLibManager _defaultEhLibManager;
    #endregion privates

    #region privates
    private readonly Type systemString = typeof(string);
    private readonly Type systemSByte = typeof(sbyte);
    private readonly Type systemByte = typeof(byte);
    private readonly Type systemChar = typeof(char);
    private readonly Type systemInt16 = typeof(short);
    private readonly Type systemUInt16 = typeof(ushort);
    private readonly Type systemInt32 = typeof(int);
    private readonly Type systemUInt32 = typeof(uint);
    private readonly Type systemInt64 = typeof(long);
    private readonly Type systemUInt64 = typeof(ulong);
    private readonly Type systemSingle = typeof(float);
    private readonly Type systemDouble = typeof(double);
    private readonly Type systemDecimal = typeof(decimal);
    private readonly Type systemDateTime = typeof(DateTime);
    private readonly Type systemDateTimeOffset = typeof(DateTimeOffset);

    private readonly Type systemNullableSByte = typeof(Nullable<sbyte>);
    private readonly Type systemNullableByte = typeof(Nullable<byte>);
    private readonly Type systemNullableChar = typeof(Nullable<char>);
    private readonly Type systemNullableInt16 = typeof(Nullable<short>);
    private readonly Type systemNullableUInt16 = typeof(Nullable<ushort>);
    private readonly Type systemNullableInt32 = typeof(Nullable<int>);
    private readonly Type systemNullableUInt32 = typeof(Nullable<uint>);
    private readonly Type systemNullableInt64 = typeof(Nullable<long>);
    private readonly Type systemNullableUInt64 = typeof(Nullable<ulong>);
    private readonly Type systemNullableSingle = typeof(Nullable<float>);
    private readonly Type systemNullableDouble = typeof(Nullable<double>);
    private readonly Type systemNullableDecimal = typeof(Nullable<decimal>);
    private readonly Type systemNullableDateTime = typeof(Nullable<System.DateTime>);
    private readonly Type systemNullableDateTimeOffset = typeof(Nullable<System.DateTimeOffset>);

    //private Type system_TimeSpan = typeof(TimeSpan);
    private readonly Type systemBoolean = typeof(bool);
    private DisplayInternalValueConverter valueConverter;
    #endregion privates

    public EhLibManager()
    {
    }

    #region properties
    public DisplayInternalValueConverter ValueConverter
    {
      get
      {
        if (valueConverter == null)
          valueConverter = CreateValueConverter();
        return valueConverter;
      }
      set
      {
        valueConverter = value;
      }
    }

    public bool DropDownDebug { get; set; }
    #endregion properties

    #region methods
    public static EhLibManager DefaultEhLibManager
    {
      get
      {
        if (_defaultEhLibManager == null)
          _defaultEhLibManager = new EhLibManager();
        return _defaultEhLibManager;
      }
      set
      {
        _defaultEhLibManager = value;
      }
    }

    public virtual bool IsAggregatableNumberType(Type type)
    {
      if (type == systemString)
        return false;
      else
        return TypeIsInteger(type) || TypeIsFloat(type) || TypeIsDecimal(type);
    }

    public virtual bool TypeIsInteger(System.Type dataType)
    {
      if ((dataType == systemSByte) ||
          (dataType == systemByte) ||
          (dataType == systemChar) ||
          (dataType == systemInt16) ||
          (dataType == systemUInt16) ||
          (dataType == systemInt32) ||
          (dataType == systemUInt32) ||
          (dataType == systemInt64) ||
          (dataType == systemUInt64)
         )
        return true;
      else
        return false;
    }

    public virtual bool TypeIsFloat(System.Type dataType)
    {
      if ((dataType == systemSingle) ||
          (dataType == systemDouble)
         )
        return true;
      else
        return false;
    }

    public virtual bool TypeIsDecimal(System.Type dataType)
    {
      if (dataType == systemDecimal)
        return true;
      else
        return false;
    }

    public virtual bool TypeIsDateTime(System.Type dataType)
    {
      if ((dataType == systemDateTime) ||
          (dataType == systemDateTimeOffset)
      )
        return true;
      else
        return false;
    }

    public virtual bool TypeIsBoolean(System.Type dataType)
    {
      if (dataType == systemBoolean)
        return true;
      else
        return false;
    }

    public virtual bool TypeIsBinary(System.Type dataType)
    {
      if (dataType == typeof(byte[]))
        return true;
      else
        return false;
    }

    public virtual bool TypeIsBinaryImage(System.Type dataType)
    {
      TypeConverter imageTypeConverter = TypeDescriptor.GetConverter(typeof(Image));

      if (typeof(System.Drawing.Image).IsAssignableFrom(dataType) || 
          imageTypeConverter.CanConvertFrom(dataType)
      )
        return true;
      else
        return false;
    }

    public virtual TypeCategory GetTypeCategoryForType(Type type)
    {
      if (type == systemString)
        return TypeCategory.String;
      else if (TypeIsInteger(type) || TypeIsFloat(type) || TypeIsDecimal(type))
        return TypeCategory.Number;
      else if (TypeIsDateTime(type))
        return TypeCategory.DateTime;
      else if (TypeIsBoolean(type))
        return TypeCategory.Boolean;
      else if (TypeIsBinary(type))
        return TypeCategory.Binary;
      else if (TypeIsBinaryImage(type))
        return TypeCategory.BinaryImage;
      else
        return TypeCategory.Unknown;
    }

    protected virtual DisplayInternalValueConverter CreateValueConverter()
    {
      return new DisplayInternalValueConverter();
    }

    public virtual HorizontalAlignment GetHorzAlignForType(Type dataType)
    {
      if (dataType == null) return HorizontalAlignment.Left;

      if (
          (dataType == systemSByte) ||
          (dataType == systemByte) ||
          (dataType == systemChar) ||
          (dataType == systemInt16) ||
          (dataType == systemUInt16) ||
          (dataType == systemInt32) ||
          (dataType == systemUInt32) ||
          (dataType == systemInt64) ||
          (dataType == systemUInt64) ||
          (dataType == systemSingle) ||
          (dataType == systemDouble) ||
          (dataType == systemDecimal) ||
          (dataType == systemDateTime) ||
          (dataType == systemDateTimeOffset) ||

          (dataType == systemNullableSByte) ||
          (dataType == systemNullableByte) ||
          (dataType == systemNullableChar) ||
          (dataType == systemNullableInt16) ||
          (dataType == systemNullableUInt16) ||
          (dataType == systemNullableInt32) ||
          (dataType == systemNullableUInt32) ||
          (dataType == systemNullableInt64) ||
          (dataType == systemNullableUInt64) ||
          (dataType == systemNullableSingle) ||
          (dataType == systemNullableDouble) ||
          (dataType == systemNullableDecimal) ||
          (dataType == systemNullableDateTime) ||
          (dataType == systemNullableDateTimeOffset)
          )
        return HorizontalAlignment.Right;
      else
        return HorizontalAlignment.Left;
    }

    #endregion methods
  }
}
