using Adw;
using OuchBrowser.Utils;
using WebKit;

namespace OuchBrowser;

internal class View
{
	public readonly TabView view;
	private readonly Window win;

	public View(TabView tabview, Window window)
	{
		view = tabview;
		win = window;
		WebKit.Module.Initialize();
	}

	private Settings InitSettings()
	{
		Settings settings = Settings.New();

		settings.SetDefaultFontFamily("serif");
		settings.SetSansSerifFontFamily("Noto Sans");
		settings.SetSerifFontFamily("Noto Serif");
		settings.SetMonospaceFontFamily("Noto Mono");
		settings.SetEnableDeveloperExtras(win.settings.GetBoolean("devtools-enabled"));

		return settings;
	}

	public WebView AddTab(string url, bool pinned)
	{
		Settings settings = InitSettings();
		WebView webview = WebView.New();

		webview.SetSettings(settings);
		webview.LoadUri(url);
		webview.SetZoomLevel(win.settings.GetDouble("zoom"));
		TabPage page;

		if (pinned)
		{
			page = view.AppendPinned(webview);
		}
		else
		{
			page = view.Append(webview);
		}

		view.SetSelectedPage(page);

		Uri uri = new Uri(url);
		if (uri.IsLoopback)
		{
			win.hostname!.SetLabel(uri.Host + ":" + uri.Port);
			page.SetTitle(uri.Host + ":" + uri.Port);
		}
		else
		{
			// TODO: this should also show the search query too maybe
			win.hostname!.SetLabel(uri.Host);
			page.SetTitle(uri.Host);
		}

		Connect(webview, win, page);

		page.OnNotify += (_, args) =>
		{
			if (args.Pspec.GetName() == "selected" && page.GetSelected() == true)
			{
				string current_uri = webview.GetUri();
				Uri uri = new Uri(current_uri);
				if (uri.IsLoopback)
				{
					win.hostname!.SetLabel(uri.Host + ":" + uri.Port);
				}
				else
				{
					// TODO: this should also show the search query too maybe
					win.hostname!.SetLabel(uri.Host);
				}

				if (webview.GetIsLoading())
				{
					win.refresh!.SetTooltipText(__("Stop loading"));
					win.refresh!.SetIconName("cross-large-symbolic");
				}
				else
				{
					win.refresh!.SetTooltipText(__("Refresh"));
					win.refresh!.SetIconName("view-refresh-symbolic");
				}

				Connect(webview, win, page);
			}
		};

		return webview;
	}

	private void Connect(WebView webview, Window window, TabPage page)
	{
		webview.OnNotify += (_, args) =>
		{
			switch (args.Pspec.GetName())
			{
				case "title":
					string title = webview.GetTitle();
					page.SetTitle(title);
					break;
			}
		};

		webview.OnLoadChanged += async (_, load_event) =>
		{
			string current_uri = webview.GetUri();
			Uri uri;
			try
			{
				uri = new Uri(current_uri);
			}
			catch
			{
				page.SetIcon(Gio.ThemedIcon.New("box-dotted-symbolic")); // set this placeholder first
				window.refresh!.SetSensitive(true);
				window.refresh!.SetTooltipText(__("Stop Loading"));
				window.url_button!.SetSensitive(true);
				window.copy_link!.SetSensitive(true);
				window.website_settings!.SetSensitive(true);
				window.sidebar_toggle!.SetSensitive(true);
				window.refresh!.SetIconName("cross-large-symbolic");
				page.SetLoading(true);
				return;
			}

			switch (load_event.LoadEvent)
			{
				case LoadEvent.Started:
					page.SetIcon(Gio.ThemedIcon.New("box-dotted-symbolic")); // set this placeholder first
					window.refresh!.SetSensitive(true);
					window.refresh!.SetTooltipText(__("Stop Loading"));
					window.url_button!.SetSensitive(true);
					window.copy_link!.SetSensitive(true);
					window.website_settings!.SetSensitive(true);
					window.sidebar_toggle!.SetSensitive(true);
					window.refresh!.SetIconName("cross-large-symbolic");
					page.SetLoading(true);
					page.SetIcon(await Favicon.GetFavicon(uri.Host));
					break;
				case LoadEvent.Committed:
					if (Url.IsIpAddress(uri.AbsoluteUri))
					{
						window.hostname!.SetLabel(uri.Host + ":" + uri.Port);
					}
					else
					{
						// TODO: this should also show the search query too maybe
						window.hostname!.SetLabel(uri.Host);
					}
					break;
				case LoadEvent.Finished:
					page.SetKeyword(current_uri);
					window.refresh!.SetTooltipText(__("Refresh"));
					window.refresh!.SetIconName("view-refresh-symbolic");
					page.SetLoading(false);

					if (webview.CanGoBack())
					{
						window.go_back!.SetSensitive(true);
					}
					else
					{
						window.go_back!.SetSensitive(false);
					}

					if (webview.CanGoForward())
					{
						window.go_forward!.SetSensitive(true);
					}
					else
					{
						window.go_forward!.SetSensitive(false);
					}

					break;
			}
		};

		webview.OnMouseTargetChanged += (_, res) =>
		{
			if (res.HitTestResult.ContextIsLink())
			{
				window.url_preview!.SetVisible(true);
				window.url_preview_label!.SetLabel(res.HitTestResult.GetLinkUri());
			}
			else
			{
				window.url_preview!.SetVisible(false);
			}
		};

		window.OnNotify += (_, args) =>
		{
			if (args.Pspec.GetName() == "fullscreened")
			{
				if (window.IsFullscreen())
				{
					window.mlv!.SetLayoutName("fullscreen");
				}
				else
				{
					window.mlv!.SetLayoutName("default");
				}
			}
		};
	}

	public string[] GetAllTabUrls()
	{
		List<string> urls = new List<string>();

		if (view.GetNPages() != 0)
		{
			for (int i = 1; i < view.GetNPages(); i++)
			{
				TabPage page = view.GetNthPage(i);
				WebView web_view = (WebView)page.Child!;

				urls.Add(web_view.GetUri());
			}
		}

		return urls.ToArray();
	}
}
