using System;
using System.Collections.Generic;
using Windows.UI;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Navigation;
using System.Diagnostics;
using Windows.UI.Xaml.Media.Imaging;
using System.Xml;
using Google.Apis.YouTube.v3.Data;
using Windows.ApplicationModel.Core;
using Windows.System;
using FoxTube.Pages;
using Windows.UI.Popups;
using Windows.Networking.Connectivity;
using Windows.ApplicationModel.Resources;
using Microsoft.Services.Store.Engagement;
using Windows.UI.Xaml.Shapes;
using Windows.UI.Xaml.Media;

namespace FoxTube
{
    /// <summary>
    /// Main app's layout
    /// </summary>
    public sealed partial class MainPage : Page
    {
        bool wasInvoked = false;
        public static event ObjectEventHandler VideoPageSizeChanged;
        readonly ResourceLoader resources = ResourceLoader.GetForCurrentView("Main");
        Dictionary<Type, string> headers;

        public Page PageContent => content.Content as Page;

        public MainPage()
        {
            InitializeComponent();

            Window.Current.SetTitleBar(AppTitleBar);
            CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = true;
            CoreApplication.GetCurrentView().TitleBar.LayoutMetricsChanged += (s, e) => SetTitleBar(s);

            SecretsVault.AuthorizationStateChanged += AuthorizationStateChanged;
            SecretsVault.SubscriptionsChanged += SecretsVault_SubscriptionsChanged;
            SecretsVault.Purchased += async (sender, e) =>
            {
                removeAds.Visibility = (e[0] as bool?).Value ? Visibility.Collapsed : Visibility.Visible;
                removeAds.Content = $"{resources.GetString("/Main/adsFree/Content")} ({e[1]})";
                if (!(bool)e[0])
                    return;

                MessageDialog dialog = new MessageDialog(resources.GetString("/Main/purchaseSuccess"));
                dialog.Commands.Add(new UICommand(resources.GetString("/Main/close"), (command) => Methods.CloseApp()));
                dialog.Commands.Add(new UICommand(resources.GetString("/Main/delay")));
                dialog.CancelCommandIndex = 1;
                dialog.DefaultCommandIndex = 0;
                await dialog.ShowAsync();
            };
            SecretsVault.Initialize();

            headers = new Dictionary<Type, string>()
            {
                { typeof(Settings), resources.GetString("/Main/settings/Content") },
                { typeof(ChannelPage), resources.GetString("/Main/channel") },
                { typeof(PlaylistPage), resources.GetString("/Main/playlist") },
                { typeof(Search), resources.GetString("/Main/searchPlaceholder/PlaceholderText") },
                { typeof(Subscriptions), resources.GetString("/Main/subscriptions/Content") },
                { typeof(History), resources.GetString("/Main/history/Content") },
                { typeof(Home), resources.GetString("/Main/home/Content") },
                { typeof(Downloads), resources.GetString("/Main/downloads/Content") }
            };

            if(StoreServicesFeedbackLauncher.IsSupported())
                feedback.Visibility = Visibility.Visible;

            PromptFeedback();
        }

        async void PromptFeedback()
        {
            if (SettingsStorage.Uptime.TotalHours >= 12 && SettingsStorage.PromptFeedback)
            {
                MessageDialog dialog = new MessageDialog(resources.GetString("/Main/feedbackMessage"));
                dialog.Commands.Add(new UICommand(resources.GetString("/Main/dontAsk"), (command) => SettingsStorage.PromptFeedback = false));
                dialog.Commands.Add(new UICommand(resources.GetString("/Main/promptLater")));
                dialog.Commands.Add(new UICommand(resources.GetString("/Main/sure"), async (command) =>
                {
                    SettingsStorage.PromptFeedback = false;
                    if (StoreServicesFeedbackLauncher.IsSupported())
                        await StoreServicesFeedbackLauncher.GetDefault().LaunchAsync();
                    else
                    {
                        MessageDialog message = new MessageDialog(resources.GetString("/Main/feedbackFail"));
                        message.Commands.Add(new UICommand(resources.GetString("/Main/sendEmail"), async (c) => await Launcher.LaunchUriAsync("mailto:michael.xfox@outlook.com".ToUri())));
                        message.Commands.Add(new UICommand(resources.GetString("/Main/goBack")));
                        message.CancelCommandIndex = 1;
                        message.DefaultCommandIndex = 0;
                        await message.ShowAsync();
                    }
                }));
                dialog.DefaultCommandIndex = 2;
                dialog.CancelCommandIndex = 1;
                await dialog.ShowAsync();
            }

            if (SettingsStorage.Uptime.TotalHours >= 24 && SettingsStorage.PromptReview)
            {
                MessageDialog dialog = new MessageDialog(resources.GetString("/Main/rate"));
                dialog.Commands.Add(new UICommand(resources.GetString("/Main/dontAsk"), (command) => SettingsStorage.PromptReview = false));
                dialog.Commands.Add(new UICommand(resources.GetString("/Main/promptLater")));
                dialog.Commands.Add(new UICommand(resources.GetString("/Main/sure"), async (command) =>
                {
                    SettingsStorage.PromptReview = false;
                    await Launcher.LaunchUriAsync("ms-windows-store://review/?ProductId=9NCQQXJTDLFH".ToUri());
                }));
                dialog.DefaultCommandIndex = 2;
                dialog.CancelCommandIndex = 1;
                await dialog.ShowAsync();
            }
        }

        public string GetPlaylist()
        {
            try { return (videoPlaceholder.Content as VideoPage).playlistId; }
            catch { return null; }
        }

        public void SetTitleBar(CoreApplicationViewTitleBar coreTitleBar = null)
        {
            if (coreTitleBar != null)
                AppTitleBar.Height = coreTitleBar.Height;

            var titleBar = ApplicationView.GetForCurrentView().TitleBar;
            
            titleBar.ButtonBackgroundColor = Colors.Transparent;
            titleBar.ButtonHoverBackgroundColor = Colors.IndianRed;
            titleBar.ButtonPressedBackgroundColor = Colors.DarkRed;
            titleBar.ButtonInactiveBackgroundColor = Colors.Transparent;
            titleBar.ButtonInactiveForegroundColor = Colors.Gray;

            if(RequestedTheme == ElementTheme.Dark || (RequestedTheme == ElementTheme.Default && Application.Current.RequestedTheme == ApplicationTheme.Dark))
                titleBar.ButtonForegroundColor = Colors.White;
            else
                titleBar.ButtonForegroundColor = Colors.Black;
        }
        
        private void SecretsVault_SubscriptionsChanged(object sender, params object[] args)
        {
            switch(args[0] as string)
            {
                case "add":
                    if (nav.MenuItems.Count < 19)
                        nav.MenuItems.Add(args[1] as Subscription);
                    break;

                case "remove":
                    Microsoft.UI.Xaml.Controls.NavigationViewItem item = nav.MenuItems.Find(i => ((i as Microsoft.UI.Xaml.Controls.NavigationViewItem).Content as StackPanel).Tag.ToString() == (args[1] as Subscription).Snippet.ResourceId.ChannelId) as Microsoft.UI.Xaml.Controls.NavigationViewItem;
                    if (item == null)
                        break;
                    else
                        nav.MenuItems.Remove(item);

                    if (SecretsVault.Subscriptions.Count >= 10)
                        nav.MenuItems.Add(SecretsVault.Subscriptions[9]);
                    break;
            }
        }
               
        private async void AuthorizationStateChanged(object sender, params object[] e)
        {
            switch(e[0] as bool?)
            {
                case true:
                    account.Visibility = Visibility.Collapsed;

                    ToolTipService.SetToolTip(avatar, $"{SecretsVault.UserInfo.Name} ({SecretsVault.UserInfo.Email})");
                    myNameFlyout.Text = SecretsVault.UserInfo.Name;
                    myEmail.Text = SecretsVault.UserInfo.Email;
                    avatarFlyout.ProfilePicture = new BitmapImage(SecretsVault.UserInfo.Picture.ToUri()) { DecodePixelHeight = 65, DecodePixelWidth = 65 };
                    ((avatar.Content as Ellipse).Fill as ImageBrush).ImageSource = new BitmapImage(SecretsVault.UserInfo.Picture.ToUri()) { DecodePixelHeight = 25, DecodePixelWidth = 25 };

                    avatar.Visibility = Visibility.Visible;

                    if(SecretsVault.UserChannel != null)
                        toChannel.Visibility =  Visibility.Visible;
                    toSubscriptions.Visibility = Visibility.Visible;
                    libHeader.Visibility = Visibility.Visible;
                    toHistory.Visibility = Visibility.Visible;
                    toLiked.Visibility = Visibility.Visible;
                    toLater.Visibility = Visibility.Visible;

                    if (SecretsVault.Subscriptions.Count > 0)
                    {
                        subsHeader.Visibility = Visibility.Visible;
                        for (int k = 0; k < SecretsVault.Subscriptions.Count && k < 10; k++)
                            nav.MenuItems.Add(SecretsVault.Subscriptions[k]);
                    }
                    HistorySet.Load();
                    break;

                case false:
                    for (int k = nav.MenuItems.Count - 1; k > 8; k--)
                        nav.MenuItems.RemoveAt(k);

                    account.Visibility = Visibility.Visible;
                    avatar.Visibility = Visibility.Collapsed;

                    toChannel.Visibility = Visibility.Collapsed;
                    toSubscriptions.Visibility = Visibility.Collapsed;
                    libHeader.Visibility = Visibility.Collapsed;
                    toHistory.Visibility = Visibility.Collapsed;
                    toLiked.Visibility = Visibility.Collapsed;
                    toLater.Visibility = Visibility.Collapsed;
                    subsHeader.Visibility = Visibility.Collapsed;

                    subsHeader.Visibility = Visibility.Collapsed;
                    break;

                default:
                    MessageDialog dialog = new MessageDialog(resources.GetString("/Main/connectErrContent"), resources.GetString("/Main/connectErrHeader"));

                    dialog.Commands.Add(new UICommand(resources.GetString("/Main/tryAgain"), (command) =>
                    {
                        SecretsVault.Authorize();
                    }));
                    dialog.Commands.Add(new UICommand(resources.GetString("/Main/quit"), (command) =>
                    {
                        Methods.CloseApp();
                    }));

                    dialog.CancelCommandIndex = 1;
                    dialog.DefaultCommandIndex = 0;

                    await dialog.ShowAsync();
                    break;
            }

            await Dispatcher.RunIdleAsync((command) => DownloadAgent.Initialize());

            wasInvoked = false;

            if (content.Content != null)
                content.Navigate(content.CurrentSourcePageType, (content.Content as NavigationPage).Parameter);
            else
                content.Navigate(typeof(Home));

            if (videoPlaceholder.Content != null)
                GoToVideo((videoPlaceholder.Content as VideoPage).videoId, (videoPlaceholder.Content as VideoPage).playlistId);
        }

        private async void Feedback_Click(object sender, RoutedEventArgs e)
        {
            await StoreServicesFeedbackLauncher.GetDefault().LaunchAsync();
        }

        private void SignIn_Click(object sender, RoutedEventArgs e)
        {
            SecretsVault.Authorize();
        }

        private void Logout_Click(object sender, RoutedEventArgs e)
        {
            SecretsVault.Deauthenticate();
        }

        public void GoToSearch(SearchParameters args)
        {
            nav.IsPaneOpen = false;
            content.Navigate(typeof(Search), args);
        }

        public void GoToChannel(string id)
        {
            content.Navigate(typeof(ChannelPage), id);
        }

        public void GoToHome()
        {
            content.Navigate(typeof(Home));
        }

        public async void GoToVideo(string id, string playlistId = null, bool incognito = false)
        {
            if (SettingsStorage.CheckConnection)
                try
                {
                    bool cancel = false;
                    ConnectionCost connection = NetworkInformation.GetInternetConnectionProfile().GetConnectionCost();
                    if (connection.NetworkCostType == NetworkCostType.Fixed || connection.NetworkCostType == NetworkCostType.Variable)
                    {
                        MessageDialog dialog = new MessageDialog(resources.GetString("/Main/metered"))
                        {
                            DefaultCommandIndex = 2,
                            CancelCommandIndex = 1
                        };
                        dialog.Commands.Add(new UICommand(resources.GetString("/Main/yes")));
                        dialog.Commands.Add(new UICommand(resources.GetString("/Main/no"), (command) => cancel = true));
                        if (SecretsVault.IsAuthorized)
                            dialog.Commands.Add(new UICommand(resources.GetString("/Main/addLater"), (command) =>
                            {
                                try
                                {
                                    PlaylistItem item = new PlaylistItem()
                                    {
                                        Snippet = new PlaylistItemSnippet()
                                        {
                                            ResourceId = new ResourceId()
                                            {
                                                Kind = "youtube#video",
                                                VideoId = id
                                            },
                                            PlaylistId = "WL"
                                        }
                                    };

                                    SecretsVault.Service.PlaylistItems.Insert(item, "snippet").Execute();
                                }
                                catch (Exception e)
                                {
                                    Debug.WriteLine(e.Message);
                                }
                                cancel = true;
                            }));

                        await dialog.ShowAsync();

                        if (cancel)
                            return;
                    }
                }
                catch { }

            if (videoPlaceholder.Content != null)
                (videoPlaceholder.Content as VideoPage).CloseVideo();

            nav.IsBackEnabled = true;
            nav.ExpandedModeThresholdWidth = short.MaxValue;
            nav.IsPaneOpen = false;

            VideoPageSizeChanged?.Invoke(this, true);
            videoPlaceholder.Navigate(typeof(VideoPage), new object[3] { id, playlistId, incognito });

            Title.Text = resources.GetString("/Main/video");
        }

        public void GoToDeveloper(string id)
        {
            content.Navigate(typeof(Settings), id);
        }

        public void GoToPlaylist(string id)
        {
            content.Navigate(typeof(PlaylistPage), id);
        }

        public void GoToHistory()
        {
            content.Navigate(typeof(History));
        }

        public void GoToDownloads()
        {
            content.Navigate(typeof(Downloads));
        }

        public void MinimizeAsInitializer()
        {
            if (videoPlaceholder.Content == null)
                return;

            if ((videoPlaceholder.Content as VideoPage).LoadingPage.State != LoadingState.Loaded)
                CloseVideo();
            else
                (videoPlaceholder.Content as VideoPage).Player.Minimize();

            Title.Text = headers[content.SourcePageType];
        }

        public void MinimizeVideo()
        {
            videoPlaceholder.Width = 432;
            videoPlaceholder.Height = 243;
            videoPlaceholder.VerticalAlignment = VerticalAlignment.Bottom;
            videoPlaceholder.HorizontalAlignment = HorizontalAlignment.Right;
            videoPlaceholder.Margin = new Thickness(0, 0, 25, 50);

            if (content.CanGoBack)
                nav.IsBackEnabled = true;
            else
                nav.IsBackEnabled = false;

            VideoPageSizeChanged?.Invoke(this, false);

            SetNavigationMenu();

            Title.Text = headers[content.SourcePageType];
        }

        void SetNavigationMenu()
        {
            if (content.SourcePageType == typeof(Home) || content.SourcePageType == typeof(Settings) || content.SourcePageType == typeof(Subscriptions))
            {
                nav.ExpandedModeThresholdWidth = 1008;
                nav.IsPaneOpen = nav.DisplayMode == Microsoft.UI.Xaml.Controls.NavigationViewDisplayMode.Expanded ? true : false;
            }
            else
                nav.ExpandedModeThresholdWidth = short.MaxValue;
        }

        public void MaximizeVideo()
        {
            videoPlaceholder.Width = double.NaN;
            videoPlaceholder.Height = double.NaN;
            videoPlaceholder.VerticalAlignment = VerticalAlignment.Stretch;
            videoPlaceholder.HorizontalAlignment = HorizontalAlignment.Stretch;
            videoPlaceholder.Margin = new Thickness(0);

            if (videoPlaceholder.Content == null)
                return;

            nav.IsBackEnabled = true;
            Title.Text = resources.GetString("/Main/video");
            nav.ExpandedModeThresholdWidth = short.MaxValue;
            nav.IsPaneOpen = false;

            VideoPageSizeChanged?.Invoke(this, true);
        }

        public void CloseVideo()
        {
            if (ApplicationView.GetForCurrentView().IsFullScreenMode)
                ApplicationView.GetForCurrentView().ExitFullScreenMode();

            videoPlaceholder.Content = null;
            GC.Collect();
            MaximizeVideo();

            if (content.CanGoBack)
                nav.IsBackEnabled = true;
            else
                nav.IsBackEnabled = false;

            VideoPageSizeChanged?.Invoke(this, false);

            SetNavigationMenu();

            Title.Text = headers[content.SourcePageType];
        }

        private void Search_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
        {
            if(!string.IsNullOrWhiteSpace(search.Text))
                GoToSearch(new SearchParameters(search.Text));
        }

        private async void Search_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
        {
            await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            {
                if (search.Text.Length > 2 && args.Reason == AutoSuggestionBoxTextChangeReason.UserInput)
                {
                    try
                    {
                        XmlDocument doc = new XmlDocument();
                        doc.Load($"http://suggestqueries.google.com/complete/search?ds=yt&client=toolbar&q={search.Text}");

                        List<string> suggestions = new List<string>();

                        for (int i = 0; i < doc["toplevel"].ChildNodes.Count && i < 5; i++)
                            suggestions.Add(doc["toplevel"].ChildNodes[i]["suggestion"].GetAttribute("data"));

                        search.ItemsSource = suggestions;
                    }
                    catch { search.ItemsSource = new List<string>(); }
                }
            });
        }

        void SetNavigationItem(object item)
        {
            try
            {
                if (nav.SelectedItem != item)
                    nav.SelectedItem = item;
                else
                    wasInvoked = false;
            }
            catch { }
        }

        public void Content_Navigated(object sender, NavigationEventArgs e)
        {
            Title.Text = headers[content.SourcePageType];

            if (!wasInvoked)
            {
                wasInvoked = true;

                if (e.SourcePageType == typeof(Settings))
                    SetNavigationItem(nav.SettingsItem);
                else if (e.SourcePageType == typeof(Subscriptions))
                    SetNavigationItem(toSubscriptions);
                else if (e.SourcePageType == typeof(Downloads))
                    SetNavigationItem(toDownloads);
                else if (e.SourcePageType == typeof(Home))
                    SetNavigationItem(toHome);
                else if (e.SourcePageType == typeof(Search))
                    SetNavigationItem(null);
                else if(e.SourcePageType == typeof(ChannelPage) && SecretsVault.IsAuthorized)
                {
                    if (e.Parameter.ToString() == SecretsVault.AccountId)
                        SetNavigationItem(toChannel);
                    else if (nav.MenuItems.Contains(SecretsVault.Subscriptions.Find(i => i.Snippet.ResourceId.ChannelId == e.Parameter.ToString())))
                        SetNavigationItem(SecretsVault.Subscriptions.Find(i => i.Snippet.ResourceId.ChannelId == e.Parameter.ToString()));
                    else
                        SetNavigationItem(null);
                }
                else if(e.SourcePageType == typeof(History))
                    SetNavigationItem(toHistory);
                else if(e.SourcePageType == typeof(PlaylistPage))
                {
                    if (e.Parameter.ToString() == SecretsVault.UserChannel.ContentDetails.RelatedPlaylists.Likes)
                        SetNavigationItem(toLiked);
                    else if (e.Parameter.Equals("WL"))
                        SetNavigationItem(toLater);
                }
            }
            else
                wasInvoked = false;

            if (content.CanGoBack)
                nav.IsBackEnabled = true;
            else
                nav.IsBackEnabled = false;

            SetNavigationMenu();

            if (videoPlaceholder.Content != null && videoPlaceholder.HorizontalAlignment == HorizontalAlignment.Stretch)
                MinimizeAsInitializer();
        }

        private void OpenContext(object sender, TappedRoutedEventArgs e)
        {
            ((Microsoft.UI.Xaml.Controls.NavigationViewItem)sender).ContextFlyout.ShowAt((Microsoft.UI.Xaml.Controls.NavigationViewItem)sender);
        }

        private void RemoveAds_Tapped(object sender, TappedRoutedEventArgs e)
        {
            SecretsVault.GetAdblock();
        }

        private void Web_Tapped(object sender, TappedRoutedEventArgs e)
        {
            content.Navigate(typeof(Home1));
        }

        private void Nav_SelectionChanged(Microsoft.UI.Xaml.Controls.NavigationView sender, Microsoft.UI.Xaml.Controls.NavigationViewSelectionChangedEventArgs args)
        {
            try
            {
                if (!wasInvoked)
                {
                    wasInvoked = true;
                    if (args.IsSettingsSelected)
                        content.Navigate(typeof(Settings));
                    else
                    {
                        if (args.SelectedItem == toHome)
                            content.Navigate(typeof(Home));
                        else if (args.SelectedItem == toHistory)
                            content.Navigate(typeof(History));
                        else if (args.SelectedItem == toLiked)
                            content.Navigate(typeof(PlaylistPage), SecretsVault.UserChannel.ContentDetails.RelatedPlaylists.Likes);
                        else if (args.SelectedItem == toLater)
                            content.Navigate(typeof(PlaylistPage), "WL");
                        else if (args.SelectedItem == toSubscriptions)
                            content.Navigate(typeof(Subscriptions));
                        else if (args.SelectedItem == toDownloads)
                            content.Navigate(typeof(Downloads));
                        else if (args.SelectedItem == toChannel)
                            content.Navigate(typeof(ChannelPage), SecretsVault.UserChannel.Id);
                        else
                            content.Navigate(typeof(ChannelPage), (args.SelectedItem as Subscription).Snippet.ResourceId.ChannelId);
                    }
                }
                else
                    wasInvoked = false;
            }
            catch { }
        }

        private void Nav_BackRequested(Microsoft.UI.Xaml.Controls.NavigationView sender, Microsoft.UI.Xaml.Controls.NavigationViewBackRequestedEventArgs args)
        {
            if (videoPlaceholder.Content != null && videoPlaceholder.Width == double.NaN)
            {
                if ((videoPlaceholder.Content as VideoPage).LoadingPage.State != LoadingState.Loaded)
                    CloseVideo();
                else if (videoPlaceholder.HorizontalAlignment == HorizontalAlignment.Stretch)
                    MinimizeAsInitializer();
            }
            else
                content.GoBack();
        }

        private void Nav_PaneClosing(Microsoft.UI.Xaml.Controls.NavigationView sender, Microsoft.UI.Xaml.Controls.NavigationViewPaneClosingEventArgs args)
        {
            AppTitle.Visibility = Visibility.Collapsed;
        }

        private void Nav_PaneOpened(Microsoft.UI.Xaml.Controls.NavigationView sender, object args)
        {
            AppTitle.Visibility = Visibility.Visible;

            if (sender.DisplayMode == Microsoft.UI.Xaml.Controls.NavigationViewDisplayMode.Expanded && sender.IsPaneOpen)
                AppTitleBar.Margin = new Thickness(40, 0, 0, 0);
            else
                AppTitleBar.Margin = new Thickness();
        }
    }
}
