using MediaBrowser.Model.DTO;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Net;
using MediaBrowser.UI.ViewModels;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Controls;
namespace MediaBrowser.UI.Pages
{
    /// 
    /// Provides a base class for pages based on a folder item (list, home)
    /// 
    public abstract class BaseFolderPage : BasePage
    {
        /// 
        /// Initializes a new instance of the  class.
        /// 
        /// The item id.
        protected BaseFolderPage(string itemId)
            : base()
        {
            ItemId = itemId;
        }
        /// 
        /// The _item id
        /// 
        private string _itemId;
        /// 
        /// Gets or sets the Id of the item being displayed
        /// 
        /// The item id.
        protected string ItemId
        {
            get { return _itemId; }
            private set
            {
                _itemId = value;
                OnPropertyChanged("ItemId");
            }
        }
        /// 
        /// The _index by
        /// 
        private string _indexBy;
        /// 
        /// Gets or sets the name of the current index function
        /// 
        /// The index by.
        public string IndexBy
        {
            get { return _indexBy; }
            private set
            {
                _indexBy = value;
                OnPropertyChanged("IndexBy");
            }
        }
        /// 
        /// The _sort by
        /// 
        private string _sortBy;
        /// 
        /// Gets or sets the name of the current sort function
        /// 
        /// The sort by.
        public string SortBy
        {
            get { return _sortBy; }
            private set
            {
                _sortBy = value;
                OnPropertyChanged("SortBy");
            }
        }
        /// 
        /// The _folder
        /// 
        private DtoBaseItem _folder;
        /// 
        /// Gets or sets the Folder being displayed
        /// 
        /// The folder.
        public DtoBaseItem Folder
        {
            get { return _folder; }
            set
            {
                _folder = value;
                OnPropertyChanged("Folder");
                OnFolderChanged();
                ReloadChildren();
            }
        }
        /// 
        /// If wrap panels are being used this will get the orientation that should be used, based on scroll direction
        /// 
        /// The wrap panel orientation.
        public Orientation WrapPanelOrientation
        {
            get
            {
                return DisplayPreferences.ScrollDirection == ScrollDirection.Horizontal ? Orientation.Vertical : Orientation.Horizontal;
            }
        }
        /// 
        /// The _display preferences
        /// 
        private DisplayPreferences _displayPreferences;
        /// 
        /// Gets of sets the current DisplayPreferences
        /// 
        /// The display preferences.
        public DisplayPreferences DisplayPreferences
        {
            get { return _displayPreferences; }
            private set
            {
                _displayPreferences = value;
                // If the page is using it's own image type and not honoring the DisplayPreferences setting, set it now
                if (_displayPreferences != null && FixedImageType.HasValue)
                {
                    _displayPreferences.PrimaryImageType = FixedImageType.Value;
                }
                NotifyDisplayPreferencesChanged();
            }
        }
        /// 
        /// The _children
        /// 
        private ItemsResult _children;
        /// 
        /// Gets or sets the children of the Folder being displayed
        /// 
        /// The children.
        public ItemsResult Children
        {
            get { return _children; }
            private set
            {
                _children = value;
                OnPropertyChanged("Children");
                ChildCount = _children.TotalRecordCount;
                OnChildrenChanged();
                DisplayChildren = DtoBaseItemViewModel.GetObservableItems(Children.Items, AveragePrimaryImageAspectRatio, DisplayPreferences);
            }
        }
        /// 
        /// The _display children
        /// 
        private ObservableCollection _displayChildren;
        /// 
        /// Gets the actual children that should be displayed.
        /// Subclasses should bind to this, not Children.
        /// 
        /// The display children.
        public ObservableCollection DisplayChildren
        {
            get { return _displayChildren; }
            private set
            {
                _displayChildren = value;
                OnPropertyChanged("DisplayChildren");
            }
        }
        /// 
        /// The _child count
        /// 
        private int _childCount;
        /// 
        /// Gets or sets the number of children within the Folder
        /// 
        /// The child count.
        public int ChildCount
        {
            get { return _childCount; }
            private set
            {
                _childCount = value;
                OnPropertyChanged("ChildCount");
            }
        }
        /// 
        /// If the page is using it's own image type and not honoring the DisplayPreferences setting, it should return it here
        /// 
        /// The type of the fixed image.
        protected virtual ImageType? FixedImageType
        {
            get { return null; }
        }
        /// 
        /// The _average primary image aspect ratio
        /// 
        private double _averagePrimaryImageAspectRatio;
        /// 
        /// Gets or sets the average primary image aspect ratio for all items
        /// 
        /// The average primary image aspect ratio.
        public double AveragePrimaryImageAspectRatio
        {
            get { return _averagePrimaryImageAspectRatio; }
            private set
            {
                _averagePrimaryImageAspectRatio = value;
                OnPropertyChanged("AveragePrimaryImageAspectRatio");
            }
        }
        /// 
        /// Gets the aspect ratio that should be used based on a given ImageType
        /// 
        /// Type of the image.
        /// System.Double.
        public double GetAspectRatio(ImageType imageType)
        {
            return GetAspectRatio(imageType, AveragePrimaryImageAspectRatio);
        }
        /// 
        /// Gets the aspect ratio that should be used based on a given ImageType
        /// 
        /// Type of the image.
        /// The average primary image aspect ratio.
        /// System.Double.
        public static double GetAspectRatio(ImageType imageType, double averagePrimaryImageAspectRatio)
        {
            switch (imageType)
            {
                case ImageType.Art:
                    return 1.777777777777778;
                case ImageType.Backdrop:
                    return 1.777777777777778;
                case ImageType.Banner:
                    return 5.414285714285714;
                case ImageType.Disc:
                    return 1;
                case ImageType.Logo:
                    return 1.777777777777778;
                case ImageType.Primary:
                    return averagePrimaryImageAspectRatio;
                case ImageType.Thumb:
                    return 1.777777777777778;
                default:
                    return 1;
            }
        }
        /// 
        /// Called when [property changed].
        /// 
        /// The name.
        public async override void OnPropertyChanged(string name)
        {
            base.OnPropertyChanged(name);
            // Reload the Folder when the itemId changes
            if (name.Equals("ItemId"))
            {
                await ReloadFolder();
            }
        }
        /// 
        /// Reloads the folder
        /// 
        /// Task.
        private async Task ReloadFolder()
        {
            try
            {
                if (string.IsNullOrEmpty(ItemId))
                {
                    Folder = await App.Instance.ApiClient.GetRootFolderAsync(App.Instance.CurrentUser.Id);
                }
                else
                {
                    Folder = await App.Instance.ApiClient.GetItemAsync(ItemId, App.Instance.CurrentUser.Id);
                }
            }
            catch (HttpException)
            {
                App.Instance.ShowDefaultErrorMessage();
            }
        }
        /// 
        /// Gets called anytime the Folder gets refreshed
        /// 
        protected virtual void OnFolderChanged()
        {
            SetBackdrops(Folder);
            DisplayPreferences = Folder.DisplayPreferences;
            if (DisplayPreferences.RememberIndexing)
            {
                IndexBy = DisplayPreferences.IndexBy;
            }
            if (DisplayPreferences.RememberSorting)
            {
                SortBy = DisplayPreferences.SortBy ?? Folder.SortOptions.FirstOrDefault();
            }
            else if (string.IsNullOrEmpty(SortBy))
            {
                SortBy = Folder.SortOptions.FirstOrDefault();
            }
        }
        /// 
        /// Gets called anytime the Children get refreshed
        /// 
        protected virtual void OnChildrenChanged()
        {
            AveragePrimaryImageAspectRatio = DtoBaseItemViewModel.GetAveragePrimaryImageAspectRatio(Children.Items);
            if (DisplayPreferences != null)
            {
                DisplayPreferences.PrimaryImageWidth = Convert.ToInt32(DisplayPreferences.PrimaryImageHeight * GetAspectRatio(DisplayPreferences.PrimaryImageType));
            }
            NotifyDisplayPreferencesChanged();
        }
        /// 
        /// Reloads the Folder's children
        /// 
        /// Task.
        public async Task ReloadChildren()
        {
            var query = new ItemQuery
            {
                ParentId = Folder.Id,
                Fields = new[] {
                                 ItemFields.UserData,
                                 ItemFields.PrimaryImageAspectRatio
                             },
                UserId = App.Instance.CurrentUser.Id,
                IndexBy = IndexBy,
                DynamicSortBy = SortBy
            };
            try
            {
                Children = await App.Instance.ApiClient.GetItemsAsync(query);
            }
            catch (HttpException)
            {
                App.Instance.ShowDefaultErrorMessage();
            }
        }
        /// 
        /// Gets called anytime a DisplayPreferences property is updated
        /// 
        public virtual void NotifyDisplayPreferencesChanged()
        {
            OnPropertyChanged("DisplayPreferences");
            if (DisplayChildren != null)
            {
                // Notify all of the child view models
                foreach (var child in DisplayChildren)
                {
                    child.AveragePrimaryImageAspectRatio = AveragePrimaryImageAspectRatio;
                    child.NotifyDisplayPreferencesChanged();
                }
            }
            OnPropertyChanged("WrapPanelOrientation");
        }
        /// 
        /// Changes the sort option on the page
        /// 
        /// The option.
        /// Task.
        public async Task UpdateSortOption(string option)
        {
            var tasks = new List();
            SortBy = option;
            if (DisplayPreferences.RememberSorting)
            {
                DisplayPreferences.SortBy = option;
                NotifyDisplayPreferencesChanged();
                tasks.Add(Task.Run(async () =>
                {
                    try
                    {
                        await App.Instance.ApiClient.UpdateDisplayPreferencesAsync(App.Instance.CurrentUser.Id, Folder.Id, DisplayPreferences);
                    }
                    catch
                    {
                        App.Instance.ShowDefaultErrorMessage();
                    }
                }));
            }
            tasks.Add(ReloadChildren());
            await Task.WhenAll(tasks);
        }
        /// 
        /// Changes the index option on the page
        /// 
        /// The option.
        /// Task.
        public async Task UpdateIndexOption(string option)
        {
            var tasks = new List();
            IndexBy = option;
            if (DisplayPreferences.RememberIndexing)
            {
                DisplayPreferences.IndexBy = option;
                NotifyDisplayPreferencesChanged();
                tasks.Add(Task.Run(async () =>
                {
                    try
                    {
                        await App.Instance.ApiClient.UpdateDisplayPreferencesAsync(App.Instance.CurrentUser.Id, Folder.Id, DisplayPreferences);
                    }
                    catch
                    {
                        App.Instance.ShowDefaultErrorMessage();
                    }
                }));
            }
            tasks.Add(ReloadChildren());
            await Task.WhenAll(tasks);
        }
        /// 
        /// Updates the index of the remember.
        /// 
        /// if set to true [remember].
        /// Task.
        public async Task UpdateRememberIndex(bool remember)
        {
            DisplayPreferences.RememberIndexing = remember;
            if (remember)
            {
                DisplayPreferences.IndexBy = IndexBy;
            }
            await App.Instance.ApiClient.UpdateDisplayPreferencesAsync(App.Instance.CurrentUser.Id, Folder.Id, DisplayPreferences);
        }
        /// 
        /// Updates the remember sort.
        /// 
        /// if set to true [remember].
        /// Task.
        public async Task UpdateRememberSort(bool remember)
        {
            DisplayPreferences.RememberSorting = remember;
            if (remember)
            {
                DisplayPreferences.SortBy = SortBy;
            }
            await App.Instance.ApiClient.UpdateDisplayPreferencesAsync(App.Instance.CurrentUser.Id, Folder.Id, DisplayPreferences);
        }
    }
}