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 Google.Apis.Oauth2.v2;
using Google.Apis.Oauth2.v2.Data;
using FoxTube.Pages;
using Windows.UI.Popups;
using Windows.Networking.Connectivity;
using Windows.ApplicationModel.Resources;

namespace FoxTube
{
    public enum Sender { Menu, Frame, None }

    /// <summary>
    /// Main app's layout
    /// </summary>
    public sealed partial class MainPage : Page
    {
        Sender s = Sender.None;
        readonly ResourceLoader resources = ResourceLoader.GetForCurrentView("Main");
        Dictionary<Type, Action> headers;
        public MainPage()
        {
            InitializeComponent();
            SetTitleBar();

            SecretsVault.AuthorizationStateChanged += AuthorizationStateChanged;
            SecretsVault.SubscriptionsChanged += SecretsVault_SubscriptionsChanged;
            SecretsVault.Purchased += (sender, e) =>
            {
                removeAds.Visibility = (e[0] as bool?).Value ? Visibility.Collapsed : Visibility.Visible;
                content.Navigate(typeof(Home));
            };
            SecretsVault.Initialize();

            headers = new Dictionary<Type, Action>()
            {
                { typeof(Settings), () => nav.Header = resources.GetString("/Main/settings/Content") },
                { typeof(ChannelPage), () => nav.Header = resources.GetString("/Main/channel") },
                { typeof(PlaylistPage), () => nav.Header = resources.GetString("/Main/playlist") },
                { typeof(Search), () => nav.Header = resources.GetString("/Main/searchPlaceholder/PlaceholderText") },
                { typeof(Subscriptions), () => nav.Header = resources.GetString("/Main/subscriptions/Content") },
                { typeof(History), () => 
                {
                    if((content.Content as History).id == "HL")
                        nav.Header = resources.GetString("/Main/history/Content");
                    else
                        nav.Header = resources.GetString("/Main/later/Content");
                } },
                { typeof(Home), () => nav.Header = resources.GetString("/Main/home/Content") },
                { typeof(Downloads), () => nav.Header = resources.GetString("/Main/downloads/Content") }
            };
        }

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

        public void SetTitleBar()
        {
            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(Application.Current.RequestedTheme == ApplicationTheme.Dark)
                titleBar.ForegroundColor = Colors.White;
            else
                titleBar.ForegroundColor = Colors.Black;

            CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = true;
        }
        
        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":
                    NavigationViewItem item = nav.MenuItems.Find(i => ((i as NavigationViewItem).Content as StackPanel).Tag.ToString() == (args[1] as Subscription).Snippet.ResourceId.ChannelId) as 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;
                    try
                    {
                        Userinfoplus info = await new Oauth2Service(SecretsVault.Initializer).Userinfo.Get().ExecuteAsync();

                        myName.Text = myNameFlyout.Text = info.Name;
                        if (string.IsNullOrWhiteSpace(info.Email))
                            myEmail.Visibility = Visibility.Collapsed;
                        else
                            myEmail.Text = info.Email;
                        avatarFlyout.ProfilePicture = new BitmapImage(info.Picture.ToUri());
                        ((avatar.Content as StackPanel).Children[0] as PersonPicture).ProfilePicture = avatarFlyout.ProfilePicture;
                    }
                    catch { }
                    avatar.Visibility = Visibility.Visible;

                    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]);
                    }
                    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;
            }

            if(e[0] as bool? != null)
                DownloadAgent.Initialize();

            s = Sender.None;
            if (content.Content != null)
                content.Navigate(content.SourcePageType);
            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, TappedRoutedEventArgs e)
        {
            await Launcher.LaunchUriAsync(new Uri("feedback-hub:"));
        }

        private async void CreateAccount_Click(object sender, RoutedEventArgs e)
        {
            await Launcher.LaunchUriAsync(new Uri("https://accounts.google.com/signup/v2/webcreateaccount?ManageAccount&flowName=GlifWebSignIn&flowEntry=SignUp"));
        }

        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)
        {
            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;

            videoPlaceholder.Navigate(typeof(VideoPage), new string[2] { id, playlistId });
        }

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

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

        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.Controls_MiniModeChanged(this, true);

            try { headers[content.SourcePageType](); }
            catch { }
        }

        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;

            SetNavigationMenu();

            try { headers[content.SourcePageType](); }
            catch { }
        }

        void SetNavigationMenu()
        {
            if (content.SourcePageType == typeof(Home) || content.SourcePageType == typeof(Settings) || content.SourcePageType == typeof(Subscriptions))
            {
                nav.ExpandedModeThresholdWidth = 1008;
                nav.IsPaneOpen = nav.DisplayMode == 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;
            nav.Header = resources.GetString("/Main/video");
            nav.ExpandedModeThresholdWidth = short.MaxValue;
            nav.IsPaneOpen = false;
        }

        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;
        }

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

        private void Search_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
        {
            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
                    s = Sender.None;
            }
            catch { }
        }

        public void Content_Navigated(object sender, NavigationEventArgs e)
        {
            try { headers[e.SourcePageType](); }
            catch { }

            if (s == Sender.None)
            {
                s = Sender.Frame;

                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))
                {
                    if (e.Parameter.ToString() == "HL")
                        SetNavigationItem(toHistory);
                    else
                        SetNavigationItem(toLater);
                }
                else if(e.SourcePageType == typeof(PlaylistPage))
                {
                    if (e.Parameter.ToString() == SecretsVault.UserChannel.ContentDetails.RelatedPlaylists.Likes)
                        SetNavigationItem(toLiked);
                }
            }
            else
                s = Sender.None;

            if(e.SourcePageType == typeof(History))
            {
                if(e.Parameter.ToString() == "HL")
                    nav.Header = resources.GetString("/Main/history/Content");
                else if(e.Parameter.ToString() == "WL")
                    nav.Header = resources.GetString("/Main/later/Content");
            }

            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)
        {
            ((NavigationViewItem)sender).ContextFlyout.ShowAt((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(NavigationView sender, NavigationViewSelectionChangedEventArgs args)
        {
            try
            {
                if (s == Sender.None)
                {
                    s = Sender.Menu;
                    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), "HL");
                        else if (args.SelectedItem == toLiked)
                            content.Navigate(typeof(PlaylistPage), SecretsVault.UserChannel.ContentDetails.RelatedPlaylists.Likes);
                        else if (args.SelectedItem == toLater)
                            content.Navigate(typeof(History), "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
                    s = Sender.None;
            }
            catch { }
        }

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

        private void Nav_PaneChanged(NavigationView sender, object args)
        {
            AppTitleBar.Visibility = nav.IsPaneOpen? Visibility.Visible : Visibility.Collapsed;
        }
    }
}
