using System;
using System.Collections.Generic;
using System.Linq;
using Irony.Interpreter;
using System.Windows.Forms;
using System.Reflection;

namespace myBuiltInMethod
{

    public class ScriptBuiltInMethod
    {

        private BrowserScriptInterfaces weblib = null;
        private FormScriptInterfaces formlib = null;

        public ScriptBuiltInMethod()
        {
            //AppDomain.CurrentDomain.AssemblyResolve += MyHandler;
        }

        //private Assembly MyHandler(object source , ResolveEventArgs e)
        //{
        //    Console.WriteLine(e.Name + "\r\n" + e.RequestingAssembly.FullName);

        //    return Assembly.Load(e.Name);
        //}

        //アプリから呼び出す。
        public void Init(BrowserScriptInterfaces browserinterfaces , FormScriptInterfaces formInterfaces)
        {
            weblib = browserinterfaces;
            formlib = formInterfaces;
        }
        //アプリから呼び出す。
        public void Init(FormScriptInterfaces formInterfaces)
        {
            weblib = null;
            formlib = formInterfaces;
        }

        //アプリから呼び出す。
        public void Init()
        {
            //weblib = null;
            //formlib = null;
        }




        #region　フォーム関連
        //**************************************************************
        //フォーム関連
        //**************************************************************
        public object GetFormControlDictionary(ScriptThread thread , object[] args)
        {
            return formlib.GetFormControlDictionary();
        }


        public object PerformClick(ScriptThread thread , object[] args)
        {
            var menu = args[0] as ToolStripItem;
            if (menu != null)
            {
                menu.PerformClick();
                return null;
            }

            var button = args[0] as Button;
            if (button != null)
            {
                button.PerformClick();
                return null;
            }

            return null;
        }


        public object msgbox(ScriptThread thread , object[] args)
        {
            string text = string.Empty;
            switch (args.Length)
            {
                case 1:
                    text = string.Empty + args[0]; //compact and safe conversion ToString()
                    break;
                case 0:
                    break;
                default:
                    text = string.Join(" " , args);
                    break;
            }
            MessageBox.Show(text);
            return null;
        }



        #endregion

        #region　配列操作

        //**************************************************************
        //配列操作
        //**************************************************************

        public object new_Array(ScriptThread thread , object[] args)
        {
            int result = 0;
            if(int.TryParse( args[0].ToString() , out result) == false) {
                result = 1;
            }
            var ar =  new object[result];
            return ar;
        }

        public object new_Dictionary(ScriptThread thread , object[] arg)
        {
            return new Dictionary<object, object>();
        }

        #endregion

        #region　リフレクション


        //**************************************************************
        //リフレクション
        //**************************************************************
 
        
        
        /// <summary>
        /// GACからアセンブリを読み込みする
        /// </summary>
        /// <param name="thread"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public object Asm_LoadWithPartialName(ScriptThread thread , object[] args)
        {
            string text = string.Empty;
            switch (args.Length)
            {
                case 1:
                    text = string.Empty + args[0]; //compact and safe conversion ToString()
                    break;
                case 0:
                    break;
                default:
                    text = string.Join(" " , args);
                    break;
            }
            var asm = System.Reflection.Assembly.LoadWithPartialName(text);
            return asm;
        }


        /// <summary>
        /// ファイルからからアセンブリを読み込みする
        /// </summary>
        /// <param name="thread"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public object Asm_LoadFrom(ScriptThread thread , object[] args)
        {
            string text = string.Empty;
            switch (args.Length)
            {
                case 1:
                    text = string.Empty + args[0]; //compact and safe conversion ToString()
                    break;
                case 0:
                    break;
                default:
                    text = string.Join(" " , args);
                    break;
            }
            var asm = System.Reflection.Assembly.LoadFrom(text);
            return asm;
        }

        public object getClass(ScriptThread thread , object[] args)
        {
            var asms = AppDomain.CurrentDomain.GetAssemblies();

            ////ピリオドの数を数える　"c.d.e" → 2　
            //var period = args[0].ToString().Split('.').Length - 1;
            //period = (period <= 0) ? 0 : period;

            //"c.d.e" → { c , d , e } → { e , d , c } → { d , c } → { c , d} → "c.d"
            var namespc = string.Join("." , args[0].ToString().Split('.').Reverse().Skip(1).Reverse());


            //アセンブリ
            var hit = asms.Where(a => a.FullName.StartsWith(namespc)).First();
            var t = hit.GetType(args[0].ToString());
            return t;
        }





        public object CreateInstance(ScriptThread thread , object[] args)
        {
            if (args.Length == 0 || args == null)
            {
                throw new ScriptException("引数がたりません");
            }

            var type = args[0] as Type;
            if (args.Length == 1)
            {
                return Activator.CreateInstance(type , null);
            }
            else
            {
                var ar = args.Skip(1).ToArray();
                return Activator.CreateInstance(type , ar);
            }
        }


        public object GetAssemblies(ScriptThread thread , object[] args)
        {
            var ret = AppDomain.CurrentDomain.GetAssemblies();
            return ret;
            
        }

        #endregion

        #region　ファイル入出力

        //**************************************************************
        //ファイル入出力
        //**************************************************************
        public object ReadFile(ScriptThread thread , object[] args)
        {
            var filepath = args[0].ToString();
            string res = "";

            if (System.IO.File.Exists(filepath))
            {
                try
                {
                    res = System.IO.File.ReadAllText(filepath, System.Text.Encoding.Default);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("ファイル読み込み失敗しました。" + Environment.NewLine + ex.Message);
                    res = "";
                }
            }
            return res;
        }

        public object WriteFile(ScriptThread thread , object[] args)
        {
            string filepath;
            string text;
            bool res = false;

            //引数チェック
            try
            {
                filepath = args[0].ToString();
                text = args[1].ToString();
            }
            catch (Exception ex)
            {
                MessageBox.Show("指定が正しくありません。" + Environment.NewLine + ex.Message);
                return false;
            }

            //******************************
            try
            {
                System.IO.File.WriteAllText(filepath , text);
                res = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show("ファイル書き込み失敗しました。" + Environment.NewLine + ex.Message);
                res = false;
            }

            return res;
        }

        #endregion


        #region　文字列操作

        //**************************************************************
        //配列操作
        //**************************************************************
        public object Array(ScriptThread thread, object[] args)
        {
            int num;
            int.TryParse(args[0].ToString() , out num);
            object[] obj = new object[num];

            return obj;

        }


        //**************************************************************
        //文字列操作
        //**************************************************************
        public object Substring(ScriptThread thread, object[] args)
        {
            var str = args[0].ToString();
            var start = int.Parse(args[1].ToString());
            var cnt = int.Parse(args[2].ToString());
            return str.Substring(start, cnt);

        }

        /// <summary>
        /// split簡易版　文字列1つ渡されて配列かえす
        /// </summary>
        /// <param name="thread"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public object Split(ScriptThread thread, object[] args)
        {
            var str = args[0].ToString();
            var delim = new string[] { args[1].ToString() };
            return str.Split(delim , StringSplitOptions.None);
        }


        //**************************************************************
        //sleep
        //**************************************************************
        public object Sleep(ScriptThread thread, object[] args)
        {
            var millisec = args[0] as int?;
            if(millisec == null)
                millisec = 100;

            var starttime = DateTime.Now;

            TimeSpan ts;

            while(true)
            {
                Application.DoEvents();
                Application.RaiseIdle(new EventArgs());
                System.Threading.Thread.Sleep(10);

                ts = DateTime.Now - starttime;
                if(ts.TotalMilliseconds > millisec) break;
            }
            return null;
        }


        public object DicToarray(ScriptThread thread, object[] args)
        {
            var dic = new Dictionary<string, object>();
            return 0;

            
            //return dic.Keys.CopyTo(new string[] { }, 0);
        }


        #endregion
    }
}
