using System;
using System.Linq;
using System.Windows.Forms;
using Gecko;

namespace myBuiltInMethod
{

    public class BrowserScriptInterfaces
    {
        //public delegate void clickButton();
        //public delegate void EvalScript(string script);

        private GeckoWebBrowser web = null;
        public bool b_navigated { get; set; }
        public bool b_navigatingFired { get; set; }
        public bool b_DocCompleted { get; set; }
        public string errmsg { set; get; }
        public GeckoMarkupDocumentViewer ZoomViewer;

        public bool checkBox_Skip_Flash_product         {get; set ;}
        public bool checkBox_Skip_Flash_battle          {get; set ;}
        public bool checkBox_AutoClick_proceedButton     {get; set ;}
        public bool checkBox_PutProduct                 { get; set; }
        public bool checkBox_login_Nobu { get; set; }
        public bool checkBox_putCurrentURL { get; set; }
        

        public BrowserScriptInterfaces(GeckoWebBrowser browser )
        {
            this.web = browser;
            web.SetInputFocus();
        }

        public void Reset()
        {
            Zoom();
            SetUserAgent();

        }

        #region Preference

        public void Zoom(float zoom = 1.0F)
        {
            ZoomViewer = web.GetMarkupDocumentViewer();
            ZoomViewer.SetFullZoomAttribute(zoom);
        }

        public void SetUserAgent(string ua =
                    "Mozilla/5.0 (Linux; U; Android 2.3.5; ja-jp; T-01D Build/F0001) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1")
        {
            Gecko.GeckoPreferences.User["general.useragent.override"] = ua;
        }

        #endregion

        #region クリック

        /// <summary>
        /// Xpath指定で対象を取得し、０番目をクリックする。
        /// indexが指定された場合は、それをクリックする。
        /// マイナス指定のときは、すべてクリックする
        /// </summary>
        /// <param name="XPATH"></param>
        /// <param name="index"></param>
        public bool ClickXpath(string XPATH, int index = 0)
        {
            bool ret = false;
            //indexがマイナス指定のときは、すべてをクリック
            if (index < 0)
            {
                ret = ClickXpath_All(XPATH);
                return ret;
            }

            try
            {
                GeckoElement[] elements = this.web.Document.GetElements(XPATH).ToArray<GeckoElement>();
                GeckoElement target;

                if (elements != null && elements.Length > 0)
                {
                    if (elements.Length > index)
                    {
                        target = elements[index];
                    }
                    else
                    {
                        target = elements[elements.Length - 1];
                    }
                    //web.StatusText = "クリックメニュー起動";
                    b_navigatingFired = false;
                    target.Click();

                    //System.Threading.Thread.Sleep(200);

                    BrowserWait();
                    ret =  true;
                }
            }
            catch
            {
                errmsg = "@@@@@@@@@@@@@@@@@@@@@@@" + Environment.NewLine 
                        + "クリックエラー" + Environment.NewLine
                        + XPATH + Environment.NewLine;
                System.Diagnostics.Debug.WriteLine(errmsg);
                ret = false;
            }
            return ret;
        }


        private bool ClickXpath_All(string XPATH)
        {
            bool ret = false;
            try
            {
                GeckoElement[] elements = this.web.Document.GetElements(XPATH).ToArray<GeckoElement>();

                if(elements != null && elements.Length > 0)
                {
                    foreach(GeckoElement item in elements)
                    {
                        //web.StatusText = "クリックメニュー起動";
                        item.Click();
                        BrowserWait();
                    }
                    ret = true;
                }
            }
            catch
            {
                errmsg = "@@@@@@@@@@@@@@@@@@@@@@@" + Environment.NewLine
                        + "クリックエラー ClickXpath_All " + Environment.NewLine
                        + XPATH + Environment.NewLine;
                System.Diagnostics.Debug.WriteLine(errmsg);
                ret = false;
            }
            return ret;

        }

        #endregion

        #region get,set properties

        public string getURL()
        {
            return web.Url.ToString();
        }


        public string[] GetTextContents(string XPATH)
        {
            if(XPATH == null) return null;

            GeckoElement[] temp = this.web.Document.GetElements(XPATH).ToArray<GeckoElement>();
            if (temp.Length == 0)
            {  
                return new string[] { "NULL" };
            }

            string[] ret = new string[temp.Length];
            for (int i = 0; i < temp.Length ; i++)
            {
                ret[i] = temp[i].TextContent;
            }
            return ret;
        }

        public string GetInnerHtml(GeckoElement ele)
        {
            if(ele == null) return null;
            return ele.InnerHtml;
        }

        public string GetOuterHtml(GeckoElement ele)
        {
            if(ele == null) return null;
            return ele.OuterHtml;
        }


        public void SetAttribute(GeckoElement ele, string attName, string attVal)
        {
            try
            {
                ele.SetAttribute(attName, attVal);
            }
            catch (Exception){}
        }



        public void SetAttribute(string Xpath, string attName, string attVal)
        {
            GeckoElement ele ;
            try
            {
                ele = web.Document.GetElements(Xpath).ToArray<GeckoElement>()[0];
                ele.SetAttribute(attName, attVal);
            }
            catch (Exception) { }
        }

        public string  GetAttribute(string Xpath, string attName)
        {
            string ret = "";

            GeckoElement ele;
            try
            {
                ele = web.Document.GetElements(Xpath).ToArray<GeckoElement>()[0];
                ret = ele.GetAttribute(attName);
            }
            catch(Exception) { }

            return ret;
        }

        public void SetTextcontents(string Xpath, string textcontent)
        {
            GeckoElement ele;
            try
            {
                ele = web.Document.GetElements(Xpath).ToArray<GeckoElement>()[0];
                ele.TextContent = textcontent;
            }
            catch (Exception) { }
        }

        public string GetTextcontents(string Xpath)
        {
            GeckoElement ele;
            string ret="";
            try
            {
                ele = web.Document.GetElements(Xpath).ToArray<GeckoElement>()[0];
                ret = ele.TextContent;
            }
            catch (Exception) { }

            return ret;
        }

        #endregion



        #region CreateElement,RemoveElement,GetElementById_

        public void CreateElement(GeckoElement ele)
        {
            web.Document.Body.AppendChild(ele);
        }

        public void RemoveElement(GeckoElement ele)
        {
            web.Document.Body.RemoveChild(ele);
        }

        public GeckoElement GetElementById_(string id)
         {
            GeckoElement ret = null; 
            try 
	        {
                ret = (GeckoElement)web.Document.GetElementById(id);
	        }
	        catch (Exception)
	        {
		        ret = null;
	        }
            return ret;
         }

        //GetElementsByName

        public GeckoElement[] GetElementsByName(string name)
        {
            GeckoElement[] ret = null;
            try
            {
                ret = (GeckoElement[])web.Document.GetElementsByName(name).ToArray();
            }
            catch(Exception)
            {

                ret = null;
            }
            return ret;
        }

        #endregion


        #region Navigate,BrowserWait

        public void Navigate(string URL)
        {
            System.Diagnostics.Debug.WriteLine("ナビゲート前");
            System.Diagnostics.Debug.WriteLine(this.web.Url.ToString());
            b_navigatingFired = false;
            this.web.Navigate(URL);

            //ナビゲート開始まで5秒まつ
            DateTime t = DateTime.Now;
            TimeSpan ts;
            while (b_navigatingFired == false)
            {
                System.Threading.Thread.Sleep(50);
                System.Diagnostics.Debug.Write("=");
                Application.DoEvents();
                //↓これないと固まることが。。
                Application.RaiseIdle(new EventArgs());

                ts = DateTime.Now - t;
                if (ts.TotalMilliseconds > 5000)
                    break;
            }

            BrowserWait();

            System.Diagnostics.Debug.WriteLine("ナビゲート完了??");
            System.Diagnostics.Debug.WriteLine(this.web.Url.ToString());
        }

        public void BrowserWait()
        {
            //ナビゲート開始まで0.2秒まつ
            DateTime t = DateTime.Now;
            TimeSpan ts;
            while (b_navigatingFired == false)
            {
                System.Threading.Thread.Sleep(50);
                System.Diagnostics.Debug.Write("+");
                Application.DoEvents();
                //↓これないと固まることが。。
                Application.RaiseIdle(new EventArgs());

                ts = DateTime.Now - t;
                if (ts.TotalMilliseconds > 200)
                    break;
            }

            //ナビゲート発生してないなら、ドキュメント読み込み完了とする
            if(b_navigatingFired == false)
            {
                b_DocCompleted = true;
                
                return;
            }


            ////////// while(web.StatusText.Length > 0 || web.IsBusy == true || this.b_navigated == false)
            while( ( b_DocCompleted == false))
            {
                System.Threading.Thread.Sleep(50);
                System.Diagnostics.Debug.Write("-");
                Application.DoEvents();
                //↓これないと固まることが。。
                Application.RaiseIdle(new EventArgs());
                
            }
            System.Diagnostics.Debug.WriteLine("browserwait...end");
            

        }

        #endregion

        #region Utilities

        public string getXpathFromElement(GeckoElement ele)
        {
            //現在の位置から、さかのぼる
            //同階層にいる同じタグを数えて、自分が何番目の兄弟か得る
            //親がいる場合は、その親をポイントして同じ処理を繰り返す
            //同じタグがなく、自分だけのときは[1]をつけない（XPATHエラーなるので）
            //後ろに兄弟がいるかもチェックする（複数ヒットをさけるため）
            if(ele == null) return "";

            int cntNodes = 0;
            int elepos = 0;
            string xpath ="";
            string targetTagname = ele.TagName.ToLower();

            if (ele.Parent == null)
            {
                return "/" + targetTagname;
            }

            foreach (GeckoNode node in ele.Parent.ChildNodes)
            {
                GeckoElement e = node.PreviousSibling as GeckoElement;
                if (e != null && e.TagName.ToLower() == targetTagname)
                {
                    cntNodes++;
                    if(e.Equals(ele))
                    {
                        elepos = cntNodes;
                    }
                }
            }

            if (elepos > 1)
            {
                xpath = targetTagname + "[" + elepos.ToString() + "]";
            }
            else
            {
                xpath = targetTagname;
            }

            //上へさかのぼる
            if (ele.ParentElement != null)
            {
                GeckoElement e = ele.ParentElement as GeckoElement;
                if (e != null)
                {
                    xpath = getXpathFromElement(e) + "/" + xpath;
                }
            }
            return xpath;
        }//getXpathFromElement

        #endregion


    }

}