using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;


namespace カブラウザもどき
{
    /// <summary>
    /// タイムアウトつき非表示ブラウザ
    /// </summary>
    class NonDispBrowser : WebBrowser
    {
        bool done;

        // タイムアウト 
        TimeSpan timeout = new TimeSpan(0, 0, 10);

        protected override void OnDocumentCompleted(WebBrowserDocumentCompletedEventArgs e)
        {
            base.OnDocumentCompleted(e);
            // このメソッドが実行されるため実際のURLを確認する
            if (e.Url == this.Url)
            {
                done = true;
            }
        }

        protected override void OnNewWindow(CancelEventArgs e)
        {
            e.Cancel = true;
            base.OnNewWindow(e);
        }

        public NonDispBrowser()
        {
            this.ScriptErrorsSuppressed = true;
        }

        public bool NavigateAndWait(string url)
        {
            base.Navigate(new Uri(url));
            done = false;
            DateTime start = DateTime.Now;

            while (done == false)
            {
                if (DateTime.Now - start > timeout)
                {
                    // タイムアウト
                    return false;
                }
                Application.DoEvents();
            }
            return true;
        }

        private void InitializeComponent()
        {
            this.SuspendLayout();
            // 
            // DispBrowser
            // 
            this.Visible = false;
            this.ResumeLayout(false);
        }
    }

    /// <summary>
    /// タイムアウト付きブラウザ
    /// </summary>
    class DispBrowser : WebBrowser
    {
        bool done;

        // タイムアウト 
        TimeSpan timeout = new TimeSpan(0, 0, 10);
        
        protected override void OnDocumentCompleted(WebBrowserDocumentCompletedEventArgs e)
        {
            base.OnDocumentCompleted(e);
            // このメソッドが実行されるため実際のURLを確認する
            if (e.Url == this.Url)
            {
                done = true;
            }
        }

        public DispBrowser()
        {
            this.ScriptErrorsSuppressed = true;
        }

        public bool NavigateAndWait(string url)
        {
            if (url == "") return false;

            this.Visible = true;

            this.Refresh(WebBrowserRefreshOption.Completely);
            base.Navigate(new Uri(url)); // ページの移動

            done = false;
            DateTime start = DateTime.Now;
            
            while (done == false)
            {
                if (DateTime.Now - start > timeout)
                {
                    // タイムアウト
                    return false;
                }
                Application.DoEvents();
            }
            return true;
        }

        private void InitializeComponent()
        {
            this.SuspendLayout();
            this.Visible = true;
            this.ResumeLayout(false);
        }
    }

    [ComVisible(true)]
    public class WebBrowserController : Control, IOleClientSite
    {
        private const int DISPID_AMBIENT_DLCONTROL = -5512;
        private WebBrowser _WebBrowser;
	    //private ComConstants _DlControl = ComConstants.DLCTL_DLIMAGES | ComConstants.DLCTL_BGSOUNDS | ComConstants.DLCTL_VIDEOS;
        private ComConstants _DlControl =  ComConstants.DLCTL_BGSOUNDS
                            | ComConstants.DLCTL_VIDEOS
                            | ComConstants.DLCTL_DLIMAGES;        
        public WebBrowserController(WebBrowser WebBrowser)
	    {
		    this._WebBrowser = WebBrowser;
            IOleObject obj = (IOleObject)this._WebBrowser.ActiveXInstance;
            obj.SetClientSite(this);
	    }

        [DispId(DISPID_AMBIENT_DLCONTROL)]
        public int Didpid_Ambient_DlControl()
        {
            return (int)this._DlControl;
        }

        private void OnAmbientPropertyChange()
        {
            UnsafeNativeMethods.IWebBrowser2 obj = (UnsafeNativeMethods.IWebBrowser2)this._WebBrowser.ActiveXInstance;
            ((IOleControl)(obj.Application)).OnAmbientPropertyChange(DISPID_AMBIENT_DLCONTROL);
        }

        public ComConstants DlControl
        {
            get { return this._DlControl; }
            set
            {
                this._DlControl = value;
                this.OnAmbientPropertyChange();
                this._WebBrowser.Refresh();
            }
        }
        public WebBrowser GetBrowser()
        {
            return this._WebBrowser;
        }
        public void GetContainer(ref object ppContainer)
        {
        }
        public void GetMoniker(uint dwAssign, uint dwWhichMoniker, ref object ppmk)
        {
        }
        public void OnShowWindow(bool fShow)
        {
        }
        public void RequestNewObjectLayout()
        {
        }
        public void SaveObject()
        {
        }
        public void ShowObject()
        {
        }
    }

    public class Sleep
    {
        public Sleep(int sec)
        {
            bool done = false;
            DateTime start = DateTime.Now;
            TimeSpan timeout = new TimeSpan(0, 0, sec);

            while (done == false)
            {
                if (DateTime.Now - start > timeout)
                {
                    return;
                }
                Application.DoEvents();
            }
            return;
        }
    }

    #region COM Interfaces & Web拡張

    public enum ComConstants : uint
    {
        DLCTL_DLIMAGES = 0x00000010,
        DLCTL_VIDEOS = 0x00000020,
        DLCTL_BGSOUNDS = 0x00000040,
        DLCTL_NO_SCRIPTS = 0x00000080,
        DLCTL_NO_JAVA = 0x00000100,
        DLCTL_NO_RUNACTIVEXCTLS = 0x00000200,
        DLCTL_NO_DLACTIVEXCTLS = 0x00000400,
        DLCTL_DOWNLOADONLY = 0x00000800,
        DLCTL_NO_FRAMEDOWNLOAD = 0x00001000,
        DLCTL_RESYNCHRONIZE = 0x00002000,
        DLCTL_PRAGMA_NO_CACHE = 0x00004000,
        DLCTL_NO_BEHAVIORS = 0x00008000,
        DLCTL_NO_METACHARSET = 0x00010000,
        DLCTL_URL_ENCODING_DISABLE_UTF8 = 0x00020000,
        DLCTL_URL_ENCODING_ENABLE_UTF8 = 0x00040000,
        DLCTL_NOFRAMES = 0x00080000,
        DLCTL_FORCEOFFLINE = 0x10000000,
        DLCTL_NO_CLIENTPULL = 0x20000000,
        DLCTL_SILENT = 0x40000000,
        DLCTL_OFFLINEIFNOTCONNECTED = 0x80000000,
        DLCTL_OFFLINE = 0x80000000
    }
    [InterfaceTypeAttribute(1)]
    [GuidAttribute("B196B288-BAB4-101A-B69C-00AA00341D07")]
    public interface IOleControl
    {
        void GetControlInfo(out object pCI);
        void OnMnemonic(ref object pMsg);
        void OnAmbientPropertyChange(int dispID);
        void FreezeEvents(bool bFreeze);
    }

    [ComImport,
    Guid("00000118-0000-0000-C000-000000000046"),
    InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IOleClientSite
    {
        void SaveObject();
        void GetMoniker(uint dwAssign, uint dwWhichMoniker, ref object ppmk);
        void GetContainer(ref object ppContainer);
        void ShowObject();
        void OnShowWindow(bool fShow);
        void RequestNewObjectLayout();
    }

    [ComImport,
    Guid("00000112-0000-0000-C000-000000000046"),
    InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IOleObject
    {
        void SetClientSite(IOleClientSite pClientSite);
        void GetClientSite(ref IOleClientSite ppClientSite);
        void SetHostNames(object szContainerApp, object szContainerObj);
        void Close(uint dwSaveOption);
        void SetMoniker(uint dwWhichMoniker, object pmk);
        void GetMoniker(uint dwAssign, uint dwWhichMoniker, object ppmk);
        void InitFromData(IDataObject pDataObject, bool fCreation, uint dwReserved);
        void GetClipboardData(uint dwReserved, ref IDataObject ppDataObject);
        void DoVerb(uint iVerb, uint lpmsg, object pActiveSite, uint lindex, uint hwndParent, uint lprcPosRect);
        void EnumVerbs(ref object ppEnumOleVerb);
        void Update();
        void IsUpToDate();
        void GetUserClassID(uint pClsid);
        void GetUserType(uint dwFormOfType, uint pszUserType);
        void SetExtent(uint dwDrawAspect, uint psizel);
        void GetExtent(uint dwDrawAspect, uint psizel);
        void Advise(object pAdvSink, uint pdwConnection);
        void Unadvise(uint dwConnection);
        void EnumAdvise(ref object ppenumAdvise);
        void GetMiscStatus(uint dwAspect, uint pdwStatus);
        void SetColorScheme(object pLogpal);
    }

    #endregion
}
