using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using Windows.ApplicationModel.Resources.Core;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml;
using ExtendedSamples.Samples;

// The data model defined by this file serves as a representative example of a strongly-typed
// model that supports notification when members are added, removed, or modified.  The property
// names chosen coincide with data bindings in the standard item templates.
//
// Applications may use this model as a starting point and build on it, or discard it entirely and
// replace it with something appropriate to their needs.

namespace ExtendedSamples.Data
{
    /// <summary>
    /// Base class for <see cref="SampleDataItem"/> and <see cref="SampleDataGroup"/> that
    /// defines properties common to both.
    /// </summary>
    [Windows.Foundation.Metadata.WebHostHidden]
    public abstract class SampleDataCommon : ExtendedSamples.Common.BindableBase
    {
        private static Uri _baseUri = new Uri("ms-appx:///");

        public SampleDataCommon(String uniqueId, String title, String subtitle, String imagePath, String description)
        {
            this._uniqueId = uniqueId;
            this._title = title;
            this._subtitle = subtitle;
            this._description = description;
            this._imagePath = imagePath;
            this.Name = title;
        }

        private string _uniqueId = string.Empty;
        public string UniqueId
        {
            get { return this._uniqueId; }
            set { this.SetProperty(ref this._uniqueId, value); }
        }

        private string _title = string.Empty;
        public string Title
        {
            get { return this._title; }
            set { this.SetProperty(ref this._title, value); }
        }

        private string _subtitle = string.Empty;
        public string Subtitle
        {
            get { return this._subtitle; }
            set { this.SetProperty(ref this._subtitle, value); }
        }

        public string Name { get; set; }

        public DataTemplate Icon
        {
            get
            {
                object res;
                if (App.Current.Resources.TryGetValue("IconC1" + Name.Replace(" ", ""), out res))
                    return (DataTemplate)res;
                else
                {
                    res = App.Current.Resources["IconC1Gray"];
                    return (DataTemplate)res;
            }
                return App.Current.Resources.TryGetValue("IconC1" + Name.Replace(" ", ""), out res) ? (DataTemplate)res :
                    (DataTemplate)App.Current.Resources["IconC1Gray"];

                //return (DataTemplate)App.Current.Resources["IconC1" + Name.Replace(" ", "")] ?? (DataTemplate)App.Current.Resources["IconC1Gray"];
        }
        }

        private string _description = string.Empty;
        public string Description
        {
            get { return this._description; }
            set { this.SetProperty(ref this._description, value); }
        }

        private ImageSource _image = null;
        private String _imagePath = null;
        public ImageSource Image
        {
            get
            {
                if (this._image == null && this._imagePath != null)
                {
                    this._image = new BitmapImage(new Uri(SampleDataCommon._baseUri, this._imagePath));
                }
                return this._image;
            }

            set
            {
                this._imagePath = null;
                this.SetProperty(ref this._image, value);
            }
        }

        public void SetImage(String path)
        {
            this._image = null;
            this._imagePath = path;
            this.OnPropertyChanged("Image");
        }
    }

    /// <summary>
    /// Generic item data model.
    /// </summary>
    public class SampleDataItem : SampleDataCommon
    {
        public SampleDataItem(String uniqueId, String title, String subtitle, String imagePath, String description, UserControl sample, SampleDataGroup group)
            : base(uniqueId, title, subtitle, imagePath, description)
        {
            this._group = group;
            this._sample = sample;
        }

        UserControl _sample = null;
        public UserControl Sample
        {
            get { return this._sample; }
            set { this.SetProperty(ref this._sample, value); }
        }

        private SampleDataGroup _group;
        public SampleDataGroup Group
        {
            get { return this._group; }
            set { this.SetProperty(ref this._group, value); }
        }
    }

    /// <summary>
    /// Generic group data model.
    /// </summary>
    public class SampleDataGroup : SampleDataCommon
    {
        public SampleDataGroup(String uniqueId, String title, String subtitle, String imagePath, String description)
            : base(uniqueId, title, subtitle, imagePath, description)
        {
        }

        private ObservableCollection<SampleDataItem> _items = new ObservableCollection<SampleDataItem>();
        public ObservableCollection<SampleDataItem> Items
        {
            get { return this._items; }
        }
        
        public IEnumerable<SampleDataItem> TopItems
        {
            // Provides a subset of the full items collection to bind to from a GroupedItemsPage
            // for two reasons: GridView will not virtualize large items collections, and it
            // improves the user experience when browsing through groups with large numbers of
            // items.
            //
            // A maximum of 12 items are displayed because it results in filled grid columns
            // whether there are 1, 2, 3, 4, or 6 rows displayed
            get { return this._items.Take(12); }
        }
    }

    /// <summary>
    /// Creates a collection of groups and items with hard-coded content.
    /// </summary>
    public sealed class SampleDataSource
    {
        private static SampleDataSource _sampleDataSource = new SampleDataSource();

        private ObservableCollection<SampleDataGroup> _allGroups = new ObservableCollection<SampleDataGroup>();
        public ObservableCollection<SampleDataGroup> AllGroups
        {
            get { return this._allGroups; }
        }

        public static IEnumerable<SampleDataGroup> GetGroups(string uniqueId)
        {
            if (!uniqueId.Equals("AllGroups")) throw new ArgumentException("Only 'AllGroups' is supported as a collection of groups");
            
            return _sampleDataSource.AllGroups;
        }

        public static SampleDataGroup GetGroup(string uniqueId)
        {
            // Simple linear search is acceptable for small data sets
            var matches = _sampleDataSource.AllGroups.Where((group) => group.UniqueId.Equals(uniqueId));
            if (matches.Count() == 1) return matches.First();
            return null;
        }

        public static SampleDataItem GetItem(string uniqueId)
        {
            // Simple linear search is acceptable for small data sets
            var matches = _sampleDataSource.AllGroups.SelectMany(group => group.Items).Where((item) => item.UniqueId.Equals(uniqueId));
            if (matches.Count() == 1) return matches.First();
            return null;
        }

        public SampleDataSource()
        {
            var group1 = new SampleDataGroup("C1Book",
                    "C1Book",
                    "Touch-based Book Items Control",
                    "Assets/DarkGray.png",
                    "Provide an interactive and unique way to visualize items with a touch controlled book control.");
            group1.Items.Add(new SampleDataItem("C1BookDemo",
                    "See it in action",
                    "Touch-based Book ItemsControl",
                    "Assets/LightGray.png",
                    "The C1Book provides an interactive and unique way to visualize items as if they are pages in a real book.",
                    new C1BookDemo(),
                    group1));
            group1.Items.Add(new SampleDataItem("C1BookPageSpan",
                    "Span Pages",
                    "Cover page and span across pages.",
                    "Assets/LightGray.png",
                    "Add a cover page and and span content across both pages.",
                    new C1BookPageSpan(),
                    group1));
            var group2 = new SampleDataGroup("C1ColorPicker",
                    "C1ColorPicker",
                    "Touch-based ColorPicker Control",
                    "Assets/DarkGray.png",
                    "The ColorPicker is a color input editor that provides a rich, interactive color selection interface.");
            group2.Items.Add(new SampleDataItem("C1ColorPickerDemo",
                    "Color Picker Page",
                    "Touch-based ColorPicker Control",
                    "Assets/LightGray.png",
                    "The ColorPicker is a color input editor that provides a rich, interactive color selection interface.",
                    new C1ColorPickerDemo(),
                    group2));
            this.AllGroups.Add(group1);
            this.AllGroups.Add(group2);

        }
    }
}
