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
    {
        readonly ResourceLoader resources = ResourceLoader.GetForCurrentView("Cards");

        public string channelId;
        public Channel item;

        SearchResource.ListRequest request;

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

        public ChannelPage()
        {
            InitializeComponent();
            
            DataTransferManager.GetForCurrentView().DataRequested += new TypedEventHandler<DataTransferManager, DataRequestedEventArgs>(Share);
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);
            if ((string)e.Parameter == null)
                loading.Error("NullReferenceException", "Unable to initialize search. Search term is not stated.");
            else
                Initialize(e.Parameter as string);
        }

        public async void Initialize(string id)
        {
            loading.Refresh();
            playlistLoading.Refresh();

            try
            {
                ChannelsResource.ListRequest infoRequest = SecretsVault.Service.Channels.List("snippet,statistics,brandingSettings");
                infoRequest.Id = channelId = 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.Image.BannerImageUrl.Contains("default"))
                    try { channelCover.Source = new BitmapImage(new Uri(item.BrandingSettings.Image.BannerImageUrl)); }
                    catch { }

                try { avatar.ProfilePicture = collapsedAvatar.ProfilePicture = new BitmapImage(new Uri(item.Snippet.Thumbnails.Medium.Url)); }
                catch { }

                Methods.FormatText(ref description, 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)
                {
                    if (SecretsVault.Subscriptions.Any(i => i.Snippet.ResourceId.ChannelId == channelId))
                    {
                        subscribe.Background = new SolidColorBrush(Colors.Transparent);
                        subscribe.Foreground = new SolidColorBrush(Colors.Gray);
                        subscribe.Content = resources.GetString("/Cards/unsubscribe");
                        collapsedBtn.Visibility = Visibility.Collapsed;
                    }
                    subscriptionPane.Visibility = Visibility.Visible;
                }

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

        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", channelId }
                });
            }
        }

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

        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(channelId))
            {
                subscribe.Background = new SolidColorBrush(Colors.Transparent);
                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 > 2)
            {
                if(content.Items.Count < 4)
                    content.Items.Add(new PivotItem()
                    {
                        Header = resources.GetString("/Channel/searchHeader"),
                        Content = new Search()
                    });

                ((content.Items[3] as PivotItem).Content as Search).Initialize(new SearchParameters(search.Text, item.Id));
                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)))
                ColapsedHeader.Opacity = 0;
            else
                ColapsedHeader.Opacity = 1;
        }

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

        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.ShowShareUI();
        }

        private void ChannelCover_ImageOpened(object sender, RoutedEventArgs e)
        {
            channelCover.Opacity = 1;
        }

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