using System;
using System.Drawing;
using System.Windows.Forms;
using CefSharp;
using CefSharp.WinForms;
using TweetDuck.Core.Controls;
using TweetDuck.Core.Handling;
using TweetDuck.Core.Handling.General;
using TweetDuck.Core.Utils;
using System.Text.RegularExpressions;
using TweetDuck.Data;
using TweetDuck.Resources;

namespace TweetDuck.Core.Other{
    sealed partial class FormGuide : Form, FormManager.IAppDialog{
        private const string GuideUrl = "https://tweetduck.chylex.com/guide/v2/";
        private const string GuidePathRegex = @"^guide(?:/v\d+)?(?:/(#.*))?";

        private static readonly ResourceLink DummyPage = new ResourceLink("http://td/dummy", ResourceHandler.FromString(""));

        public static bool CheckGuideUrl(string url, out string hash){
            if (!url.Contains("//tweetduck.chylex.com/guide")){
                hash = null;
                return false;
            }

            string path = url.Substring(url.IndexOf("/guide")+1);
            Match match = Regex.Match(path, GuidePathRegex);

            if (match.Success){
                hash = match.Groups[1].Value;
                return true;
            }
            else{
                hash = null;
                return false;
            }
        }

        public static void Show(string hash = null){
            string url = GuideUrl+(hash ?? string.Empty);
            FormGuide guide = FormManager.TryFind<FormGuide>();
            
            if (guide == null){
                FormBrowser owner = FormManager.TryFind<FormBrowser>();

                if (owner != null){
                    owner.AnalyticsFile.OpenGuide.Trigger();
                    new FormGuide(url, owner).Show(owner);
                }
            }
            else{
                guide.Reload(url);
                guide.Activate();
            }
        }

        private readonly ChromiumWebBrowser browser;
        private string nextUrl;

        private FormGuide(string url, FormBrowser owner){
            InitializeComponent();

            Text = Program.BrandName+" Guide";
            Size = new Size(owner.Size.Width*3/4, owner.Size.Height*3/4);
            VisibleChanged += (sender, args) => this.MoveToCenter(owner);
            
            this.browser = new ChromiumWebBrowser(url){
                MenuHandler = new ContextMenuGuide(owner),
                JsDialogHandler = new JavaScriptDialogHandler(),
                LifeSpanHandler = new LifeSpanHandler(),
                RequestHandler = new RequestHandlerBase(true)
            };

            browser.LoadingStateChanged += browser_LoadingStateChanged;
            browser.FrameLoadStart += browser_FrameLoadStart;
            browser.FrameLoadEnd += browser_FrameLoadEnd;
            
            browser.BrowserSettings.BackgroundColor = (uint)BackColor.ToArgb();
            browser.Dock = DockStyle.None;
            browser.Location = ControlExtensions.InvisibleLocation;

            browser.SetupResourceHandler(DummyPage);

            Controls.Add(browser);

            Disposed += (sender, args) => {
                Program.UserConfig.ZoomLevelChanged -= Config_ZoomLevelChanged;
                browser.Dispose();
            };

            Program.UserConfig.ZoomLevelChanged += Config_ZoomLevelChanged;
        }

        private void Reload(string url){
            nextUrl = url;
            browser.LoadingStateChanged += browser_LoadingStateChanged;
            browser.Dock = DockStyle.None;
            browser.Location = ControlExtensions.InvisibleLocation;
            browser.Load(DummyPage.Url);
        }

        private void browser_LoadingStateChanged(object sender, LoadingStateChangedEventArgs e){
            if (!e.IsLoading){
                if (browser.Address == DummyPage.Url){
                    browser.Load(nextUrl);
                }
                else{
                    this.InvokeAsyncSafe(() => {
                        browser.Location = Point.Empty;
                        browser.Dock = DockStyle.Fill;
                    });

                    browser.LoadingStateChanged -= browser_LoadingStateChanged;
                }
            }
        }

        private void browser_FrameLoadStart(object sender, FrameLoadStartEventArgs e){
            BrowserUtils.SetZoomLevel(browser.GetBrowser(), Program.UserConfig.ZoomLevel);
        }

        private void browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e){
            ScriptLoader.ExecuteScript(e.Frame, "Array.prototype.forEach.call(document.getElementsByTagName('A'), ele => ele.addEventListener('click', e => { e.preventDefault(); window.open(ele.getAttribute('href')); }))", "gen:links");
        }

        private void Config_ZoomLevelChanged(object sender, EventArgs e){
            BrowserUtils.SetZoomLevel(browser.GetBrowser(), Program.UserConfig.ZoomLevel);
        }
    }
}