using FoxTube.Controls;
using FoxTube.Pages;
using Google.Apis.YouTube.v3;
using Google.Apis.YouTube.v3.Data;
using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using Windows.System;
using Windows.ApplicationModel.Resources;
using Microsoft.AppCenter.Analytics;
using System.Collections.Generic;

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

        ContentFrame frame;
        public SearchParameters Parameters;
        SearchResource.ListRequest request;
        string nextToken;

        public Search()
        {
            InitializeComponent();
        }

        public string SetResults(int? count)
        {
            if (count == 1000000)
                return count + "+";
            else if (count == null)
                return "0";
            else
                return count.ToString();
        }

        public void AddItem(SearchResult result)
        {
            switch (result.Id.Kind)
            {
                case "youtube#video":
                    VideoCard vCard = new VideoCard(result.Id.VideoId);
                    list.Add(vCard);
                    break;

                case "youtube#channel":
                    if(Parameters.Channel == null)
                        list.Add(new ChannelCard(result.Id.ChannelId, result.Snippet.LiveBroadcastContent));
                    break;

                case "youtube#playlist":
                    PlaylistCard pCard = new PlaylistCard(result.Id.PlaylistId);
                    list.Add(pCard);
                    break;
            }
        }

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

            frame = ((object[])e.Parameter)[1] as ContentFrame;
            Initialize(((object[])e.Parameter)[0] as SearchParameters);
        }

        public async void Initialize(SearchParameters arg)
        {
            try
            {
                Parameters = arg;
                request = SecretsVault.Service.Search.List("id,snippet");

                searchTerm.Text = $"{resources.GetString("/Search/header")} '{Parameters.Term}'";
                if (!string.IsNullOrWhiteSpace(arg.Channel))
                {
                    request.ChannelId = arg.Channel;
                    (type.Items[2] as ComboBoxItem).Visibility = Visibility.Collapsed;
                    (grid.Children[1] as CommandBar).Visibility = Visibility.Collapsed;
                }
                else if (arg.Category != null)
                {
                    (filters.Children[0] as GridView).Items.Remove(type);
                    searchTerm.Text = $"{resources.GetString("/Search/category")} '{arg.Category.Snippet.Title}'";
                    request.VideoCategoryId = arg.Category.Id;
                }
                request.Q = arg.Term;
                request.SafeSearch = (SearchResource.ListRequest.SafeSearchEnum)SettingsStorage.SafeSearch;

                request.RegionCode = SettingsStorage.Region;
                request.RelevanceLanguage = SettingsStorage.RelevanceLanguage;

                request.MaxResults = 25;

                request.Order = (SearchResource.ListRequest.OrderEnum)arg.Filter.GetParameter(SearchParameters.Filters.Enumerations.ConversionType.Order);
                request.Type = (string)arg.Filter.GetParameter(SearchParameters.Filters.Enumerations.ConversionType.Type);
                request.PublishedAfter = (DateTime?)arg.Filter.GetParameter(SearchParameters.Filters.Enumerations.ConversionType.Date);

                if (Parameters.Filter.Type == SearchParameters.Filters.Enumerations.Type.Video)
                {
                    request.VideoDuration = (SearchResource.ListRequest.VideoDurationEnum)arg.Filter.GetParameter(SearchParameters.Filters.Enumerations.ConversionType.Duration);
                    request.VideoDefinition = (SearchResource.ListRequest.VideoDefinitionEnum)arg.Filter.GetParameter(SearchParameters.Filters.Enumerations.ConversionType.HD);
                    request.VideoDimension = (SearchResource.ListRequest.VideoDimensionEnum)arg.Filter.GetParameter(SearchParameters.Filters.Enumerations.ConversionType.ThreeD);
                    request.VideoCaption = (SearchResource.ListRequest.VideoCaptionEnum)arg.Filter.GetParameter(SearchParameters.Filters.Enumerations.ConversionType.Captions);
                    request.EventType = (SearchResource.ListRequest.EventTypeEnum?)arg.Filter.GetParameter(SearchParameters.Filters.Enumerations.ConversionType.LiveEvent);
                    request.VideoLicense = (SearchResource.ListRequest.VideoLicenseEnum)arg.Filter.GetParameter(SearchParameters.Filters.Enumerations.ConversionType.CreativeCommons);
                }

                order.SelectedIndex = (int)Parameters.Filter.Order;
                type.SelectedIndex = (int)Parameters.Filter.Type;
                duration.SelectedIndex = (int)Parameters.Filter.Duration;
                if (Parameters.Filter.HD)
                    features.SelectedItems.Add(features.Items[0]);
                if (Parameters.Filter.Is3D)
                    features.SelectedItems.Add(features.Items[1]);
                if (Parameters.Filter.Captions)
                    features.SelectedItems.Add(features.Items[2]);
                if (Parameters.Filter.LiveEvent)
                    features.SelectedItems.Add(features.Items[3]);
                if (Parameters.Filter.CreativeCommons)
                    features.SelectedItems.Add(features.Items[4]);

                SearchListResponse response = await request.ExecuteAsync();
                resultsCount.Text = $"{resources.GetString("/Search/found")}: {SetResults(response.PageInfo.TotalResults)} {resources.GetString("/Search/items")}";

                if (!string.IsNullOrWhiteSpace(response.NextPageToken))
                    nextToken = response.NextPageToken;
                else
                    more.Visibility = Visibility.Collapsed;

                list.Clear();
                foreach (SearchResult item in response.Items)
                    AddItem(item);

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

        private void ToggleFilters_Click(object sender, RoutedEventArgs e)
        {
            if(filters.Visibility == Visibility.Collapsed)
            {
                filters.Visibility = Visibility.Visible;
                toggleFilters.Content = resources.GetString("/Search/hideFilters");
            }
            else
            {
                filters.Visibility = Visibility.Collapsed;
                toggleFilters.Content = resources.GetString("/Search/filters/Content");
            }
        }

        private void AppBarButton_Click(object sender, RoutedEventArgs e)
        {
            frame.Refresh();
        }

        private async void More_Clicked()
        {
            request.PageToken = nextToken;
            SearchListResponse response = await request.ExecuteAsync();
            foreach (SearchResult item in response.Items)
                AddItem(item);

            if (response.NextPageToken != null)
            {
                nextToken = response.NextPageToken;
                more.Complete();
            }
            else
                more.Visibility = Visibility.Collapsed;
        }

        private void Type_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            try
            {
                if (type.SelectedIndex == 1)
                {
                    duration.Visibility = Visibility.Visible;
                    featBtn.Visibility = Visibility.Visible;
                }
                else
                {
                    duration.Visibility = Visibility.Collapsed;
                    featBtn.Visibility = Visibility.Collapsed;
                    duration.SelectedIndex = 0;
                    features.SelectedItems.Clear();
                }
            }
            catch (NullReferenceException) { }
        }

        private async void InBrowser_Click(object sender, RoutedEventArgs e)
        {
            await Launcher.LaunchUriAsync(new Uri($"https://www.youtube.com/results?search_query={searchTerm}"));
        }

        private void Apply_Click(object sender, RoutedEventArgs e)
        {
            Parameters.Filter.HD = features.SelectedItems.Contains(features.Items[0]);
            Parameters.Filter.Is3D = features.SelectedItems.Contains(features.Items[1]);
            Parameters.Filter.Captions = features.SelectedItems.Contains(features.Items[2]);
            Parameters.Filter.LiveEvent = features.SelectedItems.Contains(features.Items[3]);
            Parameters.Filter.CreativeCommons = features.SelectedItems.Contains(features.Items[4]);

            Parameters.Filter.Order = (SearchParameters.Filters.Enumerations.Order)order.SelectedIndex;
            Parameters.Filter.Type = (SearchParameters.Filters.Enumerations.Type)type.SelectedIndex;
            Parameters.Filter.Date = (SearchParameters.Filters.Enumerations.Date)date.SelectedIndex;
            Parameters.Filter.Duration = (SearchParameters.Filters.Enumerations.Duration)duration.SelectedIndex;
            
            Initialize(Parameters);
        }
    }
}
