using System;
using System.Linq;
using Windows.Foundation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Google.Apis.YouTube.v3;
using Google.Apis.YouTube.v3.Data;
using Windows.UI.Xaml.Media.Imaging;
using FoxTube.Controls;
using Windows.ApplicationModel.DataTransfer;
using Windows.System;
using Windows.UI;
using Windows.ApplicationModel.Resources;
using Microsoft.AppCenter.Analytics;
using System.Collections.Generic;

namespace FoxTube.Pages
{
    /// <summary>
    /// Channel page
    /// </summary>
    public sealed partial class ChannelPage : Page, INavigationPage
    {
        public object Parameter { get; set; } = null;
        readonly ResourceLoader resources = ResourceLoader.GetForCurrentView("Cards");

        public Channel item;

        SearchResource.ListRequest request;

        private string videoToken, playlistToken;
        private bool playlistLoaded = false;

        public ChannelPage()
        {
            InitializeComponent();
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);

            Parameter = e.Parameter;
            Initialize(e.Parameter as string);
        }

        public async void Initialize(string id)
        {
            try
            {
                ChannelsResource.ListRequest infoRequest = SecretsVault.Service.Channels.List("snippet,statistics,brandingSettings");
                infoRequest.Id = id;
                
                item = (await infoRequest.ExecuteAsync()).Items[0];

                title.Text = collapsedTitle.Text = item.Snippet.Title;
                subscribers.Text = $"{item.Statistics.SubscriberCount:0,0} {resources.GetString("/Cards/subscribers")}";
                videosCount.Text = $"{item.Statistics.VideoCount:0,0} {resources.GetString("/Cards/videos")}";

                if (item.BrandingSettings != null && !item.BrandingSettings.Image.BannerImageUrl.Contains("default"))
                    channelCover.Source = new BitmapImage(item.BrandingSettings.Image.BannerTabletExtraHdImageUrl == null ?
                        item.BrandingSettings.Image.BannerImageUrl.ToUri() : item.BrandingSettings.Image.BannerTabletHdImageUrl.ToUri());

                avatar.ProfilePicture = collapsedAvatar.ProfilePicture = new BitmapImage(item.Snippet.Thumbnails.Medium.Url.ToUri()) { DecodePixelHeight = 100, DecodePixelWidth = 100 };

                description.FormatText(item.Snippet.Description);

                request = SecretsVault.Service.Search.List("id");
                request.ChannelId = id;
                request.Type = "video";
                request.Order = SearchResource.ListRequest.OrderEnum.Date;
                request.MaxResults = 25;

                SearchListResponse response = await request.ExecuteAsync();
                
                foreach (SearchResult i in response.Items)
                    videoList.Add(new VideoCard(i.Id.VideoId));

                if (!string.IsNullOrWhiteSpace(response.NextPageToken))
                    videoToken = response.NextPageToken;
                else
                    videoMore.Visibility = Visibility.Collapsed;

                if (SecretsVault.IsAuthorized)
                {
                    logIn.Visibility = Visibility.Collapsed;
                    if (SecretsVault.Subscriptions.Any(i => i.Snippet.ResourceId.ChannelId == item.Id))
                    {
                        subscribe.Background = Background;
                        subscribe.Foreground = new SolidColorBrush(Colors.Gray);
                        subscribe.Content = resources.GetString("/Cards/unsubscribe");
                    }
                    else
                        collapsedBtn.Visibility = Visibility.Visible;
                    subscribe.Visibility = Visibility.Visible;
                }

                if (id == SecretsVault.AccountId)
                {
                    infoPanel.ColumnDefinitions[2].Width = new GridLength(0);
                    collapsedBtn.Visibility = Visibility.Collapsed;
                }

                ScrollViewer_ViewChanged(this, null);

                Methods.MainPage.PageContent.LoadingPage.Close();
            }
            catch (System.Net.Http.HttpRequestException)
            {
                Methods.MainPage.PageContent.LoadingPage.Error("System.Net.Http.HttpRequestException", "Unable to connect to Google servers.", true);
            }
            catch (Exception e)
            {
                if(item == null)
                {
                    Methods.MainPage.PageContent.LoadingPage.Error("ChannelNotFound", "Such channel doesn't exist");
                    return;
                }

                Methods.MainPage.PageContent.LoadingPage.Error(e.GetType().ToString(), e.Message);
                Analytics.TrackEvent("Channel loading error", new Dictionary<string, string>()
                {
                    { "Exception", e.GetType().ToString() },
                    { "Message", e.Message },
                    { "Channel ID", item.Id },
                    { "StackTrace", e.StackTrace }
                });
            }
        }

        async void LoadPlaylist()
        {
            try
            {
                playlistLoading.Refresh();
                
                request.Type = "playlist";

                SearchListResponse response = await request.ExecuteAsync();
                
                foreach (SearchResult i in response.Items)
                    playlistList.Add(new PlaylistCard(i.Id.PlaylistId));

                if (!string.IsNullOrWhiteSpace(response.NextPageToken))
                    playlistToken = response.NextPageToken;
                else
                    playlistMore.Visibility = Visibility.Collapsed;

                playlistLoaded = true;
                playlistLoading.Close();
            }
            catch (System.Net.Http.HttpRequestException)
            {
                playlistLoading.Error("System.Net.Http.HttpRequestException", "Unable to connect to Google servers.", true);
            }
            catch (Exception e)
            {
                playlistLoading.Error(e.GetType().ToString(), e.Message);
                Analytics.TrackEvent("Channel playlists list loading error", new Dictionary<string, string>()
                {
                    { "Exception", e.GetType().ToString() },
                    { "Message", e.Message },
                    { "Channel ID", item.Id },
                    { "StackTrace", e.StackTrace }
                });
            }
        }

        private void Content_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (content.SelectedIndex == 1 && !playlistLoaded)
                LoadPlaylist();

            if (content.SelectedIndex == 0)
                ScrollViewer_ViewChanged(this, null);
            else
                showHeader.Begin();
        }

        private async void ShowMorePlaylists_Click()
        {
            request.Type = "playlist";
            request.PageToken = playlistToken;
            SearchListResponse response = await request.ExecuteAsync();
            
            foreach (SearchResult i in response.Items)
                playlistList.Add(new PlaylistCard(i.Id.PlaylistId));

            if (string.IsNullOrWhiteSpace(response.NextPageToken))
                playlistMore.Visibility = Visibility.Collapsed;
            else
            {
                playlistToken = response.NextPageToken;
                playlistMore.Complete();
            }
        }

        private async void VideoMore_Clicked()
        {
            request.Type = "video";
            request.PageToken = videoToken;
            SearchListResponse response = await request.ExecuteAsync();

            foreach (SearchResult i in response.Items)
                videoList.Add(new VideoCard(i.Id.VideoId));

            if (string.IsNullOrWhiteSpace(response.NextPageToken))
                videoMore.Visibility = Visibility.Collapsed;
            else
            {
                videoToken = response.NextPageToken;
                videoMore.Complete();
            }
        }

        private async void Subscribe_Click(object sender, RoutedEventArgs e)
        {
            if(await SecretsVault.ChangeSubscriptionState(item.Id))
            {
                subscribe.Background = Background;
                subscribe.Foreground = new SolidColorBrush(Colors.Gray);
                subscribe.Content = resources.GetString("/Cards/unsubscribe");
                collapsedBtn.Visibility = Visibility.Collapsed;
            }
            else
            {
                subscribe.Background = new SolidColorBrush(Colors.Red);
                subscribe.Foreground = new SolidColorBrush(Colors.White);
                subscribe.Content = resources.GetString("/Cards/subscribe/Content");
                collapsedBtn.Visibility = Visibility.Visible;
            }
        }

        private void Hyperlink_Click(Windows.UI.Xaml.Documents.Hyperlink sender, Windows.UI.Xaml.Documents.HyperlinkClickEventArgs args)
        {
            SecretsVault.Authorize();
        }

        private void AutoSuggestBox_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
        {
            if (search.Text.Length < 3)
                return;

            if (content.Items.Count < 4)
                content.Items.Add(new PivotItem()
                {
                    Header = resources.GetString("/Channel/searchHeader"),
                    Content = new ContentFrame()
                });

            ((content.Items[3] as PivotItem).Content as ContentFrame).Frame.Navigate(typeof(Search), new object[] { new SearchParameters(search.Text, item.Id), (content.Items[3] as PivotItem).Content as ContentFrame });
            content.SelectedIndex = 3;
        }

        private void ScrollViewer_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
        {
            Rect panel = infoPanel.TransformToVisual(videoScroll).TransformBounds(new Rect(0.0, 0.0, infoPanel.ActualWidth, infoPanel.ActualHeight));
            Rect view = new Rect(0.0, 0.0, videoScroll.ActualWidth, videoScroll.ActualHeight);

            if (view.Contains(new Point(panel.Left, panel.Bottom)))
                hideHeader.Begin();
            else
                showHeader.Begin();
        }

        private void Refresh_Click(object sender, RoutedEventArgs e)
        {
            Methods.MainPage.PageContent.Refresh();
        }

        private async void InBrowser_Click(object sender, RoutedEventArgs e)
        {
            await Launcher.LaunchUriAsync(new Uri($"https://www.youtube.com/channel/{item.Id}"));
        }

        private void Share_Click(object sender, RoutedEventArgs e)
        {
            DataTransferManager.GetForCurrentView().DataRequested += new TypedEventHandler<DataTransferManager, DataRequestedEventArgs>(Share);
            DataTransferManager.ShowShareUI();
        }

        private void ChannelCover_ImageOpened(object sender, RoutedEventArgs e)
        {
            showThumb.Begin();
            infoStack.Margin = new Thickness(0, channelCover.ActualHeight, 0, 0);
        }

        private void Grid_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            infoStack.Margin = new Thickness(0, channelCover.ActualHeight, 0, 0);
        }

        private void Share(DataTransferManager sender, DataRequestedEventArgs args)
        {
            Methods.Share(args,
                item.Snippet.Thumbnails.Medium.Url,
                item.Snippet.Title,
                string.IsNullOrWhiteSpace(item.Snippet.CustomUrl) ? $"https://www.youtube.com/channel/{item.Id}" : $"https://www.youtube.com/user/{item.Snippet.CustomUrl}",
                resources.GetString("/Cards/channelShare"));
        }
    }
}
