// == LICENSE INFORMATION ==
/*
 * First author tiritomato 2013.
 * This program is distributed under the GNU General Public License(GPL).
 * support blog (Japanese only) http://d.hatena.ne.jp/tiri_tomato/
 */
// == LICENSE INFORMATION ==

using System;

namespace UVTexIntegra.Scripting
{
    //! @addtogroup UVTexIntegra-Scripting名前空間
    //! @{

    //! @brief Instanceがnullでない場合に、インスタンス内部の型のTypeConverterを呼び出します。
    public class InnerObjectConverter : System.ComponentModel.TypeConverter
    {
        public static System.ComponentModel.TypeConverter GetInnerTypeConverter(ref Type innerType, System.ComponentModel.ITypeDescriptorContext context)
        {
            if ((context == null) || (context.Instance == null)) innerType = null;
            else innerType = context.Instance.GetType();
            if (innerType != null) return System.ComponentModel.TypeDescriptor.GetConverter(innerType);
            return null;
        }

        public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, Type sourceType)
        {
            Type innerType = null;
            System.ComponentModel.TypeConverter innerTypeConverter = GetInnerTypeConverter(ref innerType, context);
            if (innerTypeConverter != null) return innerTypeConverter.CanConvertFrom(context, sourceType);
            return base.CanConvertFrom(context, sourceType);
        }

        public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, Type destinationType)
        {
            Type innerType = null;
            System.ComponentModel.TypeConverter innerTypeConverter = GetInnerTypeConverter(ref innerType, context);
            if (innerTypeConverter != null) return innerTypeConverter.CanConvertTo(context, destinationType);
            return base.CanConvertTo(context, destinationType);
        }

        public override System.Object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context,
            System.Globalization.CultureInfo culture, System.Object value)
        {
            Type innerType = null;
            System.ComponentModel.TypeConverter innerTypeConverter = GetInnerTypeConverter(ref innerType, context);
            if (innerTypeConverter != null) return innerTypeConverter.ConvertFrom(context, culture, value);
            return base.ConvertFrom(context, culture, value);
        }

        public override System.Object ConvertTo(System.ComponentModel.ITypeDescriptorContext context,
            System.Globalization.CultureInfo culture, System.Object value, Type destinationType)
        {
            Type innerType = null;
            System.ComponentModel.TypeConverter innerTypeConverter = GetInnerTypeConverter(ref innerType, context);
            if (innerTypeConverter != null) return innerTypeConverter.ConvertTo(context, culture, value, destinationType);
            return base.ConvertTo(context, culture, value, destinationType);
        }

    }

    //! @brief Instanceがnullでない場合に、インスタンス内部の型のTypeConverterを呼び出します。ExpandableObjectConverterを継承します。
    public class ExpandableInnerObjectConverter : System.ComponentModel.ExpandableObjectConverter
    {
        public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, Type sourceType)
        {
            Type innerType = null;
            System.ComponentModel.TypeConverter innerTypeConverter = InnerObjectConverter.GetInnerTypeConverter(ref innerType, context);
            if (innerTypeConverter != null) return innerTypeConverter.CanConvertFrom(context, sourceType);
            return base.CanConvertFrom(context, sourceType);
        }

        public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, Type destinationType)
        {
            Type innerType = null;
            System.ComponentModel.TypeConverter innerTypeConverter = InnerObjectConverter.GetInnerTypeConverter(ref innerType, context);
            if (innerTypeConverter != null) return innerTypeConverter.CanConvertTo(context, destinationType);
            return base.CanConvertTo(context, destinationType);
        }

        public override System.Object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context,
            System.Globalization.CultureInfo culture, System.Object value)
        {
            Type innerType = null;
            System.ComponentModel.TypeConverter innerTypeConverter = InnerObjectConverter.GetInnerTypeConverter(ref innerType, context);
            if (innerTypeConverter != null) return innerTypeConverter.ConvertFrom(context, culture, value);
            return base.ConvertFrom(context, culture, value);
        }

        public override System.Object ConvertTo(System.ComponentModel.ITypeDescriptorContext context,
            System.Globalization.CultureInfo culture, System.Object value, Type destinationType)
        {
            Type innerType = null;
            System.ComponentModel.TypeConverter innerTypeConverter = InnerObjectConverter.GetInnerTypeConverter(ref innerType, context);
            if (innerTypeConverter != null) return innerTypeConverter.ConvertTo(context, culture, value, destinationType);
            return base.ConvertTo(context, culture, value, destinationType);
        }
    }

    //! @}
}
