// == 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 ==

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

    public class ColorTypeConverter : System.ComponentModel.TypeConverter
    {
        public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType)
        {
            if ((destinationType == typeof(System.String)) && (value is System.Drawing.Color))
            {
                System.Drawing.Color col = (System.Drawing.Color)(value);
                return System.String.Format("ARGB:{0},{1},{2},{3}", col.A, col.R, col.G, col.B);
            }
            return base.ConvertTo(context, culture, value, destinationType);
        }

        public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType)
        {
            if (sourceType == typeof(System.String)) return true;
            return base.CanConvertFrom(context, sourceType);
        }

        public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            System.String source = value as System.String;
            if (source != null)
            {
                int[] num_elements = new int[4] { 0, 0, 0, 0 };
                System.String[] split = source.Split(new System.Char[] { ':' }, System.StringSplitOptions.RemoveEmptyEntries);
                System.String element = ((1 <= split.Length) ? split[1] : source).Trim();
                System.String[] elements = element.Split(new System.Char[] { ',', '.', '/', ';', '-', '+' }, System.StringSplitOptions.RemoveEmptyEntries);
                int length = System.Math.Min(num_elements.Length, elements.Length);
                for (int index = 0; index < length; index++) int.TryParse(elements[index].Trim(), out num_elements[index]);
                return System.Drawing.Color.FromArgb(num_elements[0], num_elements[1], num_elements[2], num_elements[3]);
            }
            return base.ConvertFrom(context, culture, value);
        }
    }

    public class ColorTypeEditor : System.Drawing.Design.ColorEditor/*UITypeEditor*/
    {
        public override System.Drawing.Design.UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
        {
            if ((context != null) && (context.Instance != null)) return System.Drawing.Design.UITypeEditorEditStyle.Modal;
            return base.GetEditStyle(context);
        }

        public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, System.IServiceProvider provider, object value)
        {
            if (value is System.Drawing.Color)
            {
                System.Drawing.Color source = (System.Drawing.Color)value;
                int regAlpha = source.A;
                using (System.Windows.Forms.ColorDialog dlg = new System.Windows.Forms.ColorDialog())
                {
                    dlg.Color = source;
                    if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.Cancel) return value;
                    return System.Drawing.Color.FromArgb(regAlpha, dlg.Color.R, dlg.Color.G, dlg.Color.B);
                }
            }
            return base.EditValue(context, provider, value);
        }
    }

    //! @brief アセンブリのロード/コンパイル情報と、１つのアセンブリに紐付けられた複数インスタンスのうちのひとつをセットにしてプロパティグリッドに表示するためのクラス
	[System.ComponentModel.TypeConverter(typeof(Scripting.PropertyCustomTypeConverter))]
	public class ScriptObject : IScriptObject {
		
        //! @brief 関連するアセンブリ情報を取得します
		[System.ComponentModel.TypeConverter(typeof(ExpandableInnerObjectConverter))]
		[System.ComponentModel.Description("ロード元のDLL情報。またはコンパイルの設定")]
		[Scripting.PropertyCustomTypeConverter.DisplayNameAttribute("アセンブリ")]
        public LoadedAssembly Assembly { get { return m_assembly; } }

        //! @brief 焼き込みカンバスの背景色を設定します
        [System.ComponentModel.Description("カンバスの下地色"), System.ComponentModel.Category("一般設定")]
        [Scripting.PropertyCustomTypeConverter.DisplayNameAttribute("背景色")]
        [System.ComponentModel.TypeConverter(typeof(UVTexIntegra.Scripting.ColorTypeConverter))]
        [System.ComponentModel.Editor(typeof(UVTexIntegra.Scripting.ColorTypeEditor), typeof(System.Drawing.Design.UITypeEditor))]
        public System.Drawing.Color BakeTextureBackColor
        {
            get
            {
                if (m_config == null) return System.Drawing.Color.Empty;
                return System.Drawing.Color.FromArgb(m_config.BakeTextureBaseColor);
            }
            set
            {
                if (m_config != null) m_config.BakeTextureBaseColor = value.ToArgb();
            }
        }

        //! 焼き込みカンバスにポリゴンを描画する時のボーダーの太さを設定します。
        [System.ComponentModel.Description("ポリゴンを描画する時のボーダーの太さ"), System.ComponentModel.Category("一般設定")]
        [Scripting.PropertyCustomTypeConverter.DisplayNameAttribute("太さ")]
        public float BakeTextureBorder
        {
            get
            {
                if (m_config == null) return 0.0f;
                return m_config.BakeTextureBorder;
            }
            set
            {
                if (m_config != null) m_config.BakeTextureBorder = value;
            }
        }

        //! @brief 焼き込み画像を出力する時のサイズを設定します。
        [System.ComponentModel.Description("画像を出力する時のサイズ(カンバス上では常に正方形ですが、保存する時には正方形以外でも保存できます)"), System.ComponentModel.Category("一般設定")]
        [Scripting.PropertyCustomTypeConverter.DisplayNameAttribute("保存サイズ")]
        public System.Drawing.Size BakeTextureSize
        {
            get
            {
                if (m_config == null) return System.Drawing.Size.Empty;
                return m_config.BakeTextureImageSize;
            }
            set
            {
                if (m_config != null) m_config.BakeTextureImageSize = value;
            }
        }

		//! @brief インスタンスの表示名を取得します
		//! @details 表示名は次の書式で生成されます。 "ScriptMain.Name ( LoadedAssembly.FilePath )"
		[System.ComponentModel.BrowsableAttribute(false)]
		public System.String DisplayName
        {
			get
            {
                System.String assembly_name = null;
			    if ( m_assembly != null ) assembly_name = m_assembly.DisplayName;
			    if ( System.String.IsNullOrEmpty( assembly_name ) ) assembly_name = "()";
			    else assembly_name = "( " + assembly_name.Trim() + " )";
			    System.String instance_name = null;
			    if ( m_instance != null ) instance_name = m_instance.Name;
			    if ( System.String.IsNullOrEmpty(instance_name) ) return assembly_name;
			    return instance_name + " " + assembly_name;
            }
        }

        [System.ComponentModel.Description("スクリプトがシリアライズ可能かどうか。詳しくはScriptMain.IsSerializable()を参照してください。")]
        public bool Serializable { get { return m_isSerializable; } }

        [System.ComponentModel.Description("スクリプトがシリアライズ可能で、Scripting.SerializeSaveAttributeがtrueに設定されているかどうか。詳しくはScriptMain.IsSerializeSave()を参照してください。")]
        public bool SerializeSave { get { return m_isSerializeSave; } }

		//! @brief ScriptMainインスタンスを取得します。
        [System.ComponentModel.TypeConverter(typeof(ExpandableInnerObjectConverter))]
	    [System.ComponentModel.Description("スクリプトインスタンスのプロパティ設定を行います")]
	    [Scripting.PropertyCustomTypeConverter.DisplayNameAttribute("スクリプトメンバ")]
		public Scripting.ScriptMain ScriptMain { get { return m_instance; } }

		//! @brief コンストラクタ
		public ScriptObject(LoadedAssembly assembly, Scripting.ScriptMain instance, IBakeTextureConfig config)
        {
            m_assembly = assembly;
            m_instance = instance;
            m_isSerializable = false;
            m_isSerializeSave = false;
            m_config = config;
            if (instance != null)
            {
                m_isSerializable = instance.IsSerializable();
                m_isSerializeSave = instance.IsSerializeSave();
            }
        }

		private readonly LoadedAssembly m_assembly;
		private readonly Scripting.ScriptMain m_instance;
        private readonly bool m_isSerializable;
        private readonly bool m_isSerializeSave;
        private readonly IBakeTextureConfig m_config;
    }

    //! @}
}
