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 PdfViewerSamples;

// 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 PdfViewerSamples.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 : PdfViewerSamples.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"];
        }
        }

        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("All Samples",
                    "All Samples",
                    "A Document Viewer for Windows Store App Developers",
                    "Assets/DarkGray.png",
                    "Add document viewing capabilities to your Windows Store apps");
            group1.Items.Add(new SampleDataItem("See it in action",
                    "See it in action",
                    "See the PdfViewer in action!",
                    "Assets/LightGray.png",
                    "Display arbitrary PDF documents in your apps.",
                    new PdfViewerDemoPage(),
                    group1));
            group1.Items.Add(new SampleDataItem("Orientation",
                    "Orientation",
                    "Enable horizontal orientation.",
                    "Assets/DarkGray.png",
                    "Enable horizontal scrolling in addition to vertical.",
                    new Orientation(),
                    group1));
            group1.Items.Add(new SampleDataItem("Large Files",
                    "Large Files",
                    "Load large files from the web.",
                    "Assets/DarkGray.png",
                    "Load large files from the web.",
                    new LargeFile(),
                    group1));
            group1.Items.Add(new SampleDataItem("Find Text",
                   "Find Text",
                   "Search text in the pdf file.",
                   "Assets/DarkGray.png",
                   "Search text in the pdf file.",
                   new FindText(),
                   group1));
            group1.Items.Add(new SampleDataItem("Bookmarks",
                   "Bookmarks",
                   "Navigate to bookmarks in the document.",
                   "Assets/DarkGray.png",
                   "Display bookmarks and navigate to them.",
                   new BookmarksDemo(),
                   group1));
            group1.Items.Add(new SampleDataItem("Printing",
                   "Printing",
                   "Print the pages of PdfViewer.",
                   "Assets/DarkGray.png",
                   "Use the GetPages method to send pages to a printer device. Swipe out the Devices charm or click the Print button to invoke printing.",
                   new Printing(),
                   group1));
            group1.Items.Add(new SampleDataItem("FlipView",
                  "FlipView",
                  "Display PDF pages in any control.",
                  "Assets/DarkGray.png",
                  "Use the GetPages method to populate any ItemsControl with pages from a PDF. This demo shows a FlipView example.",
                  new PdfFlipView(),
                  group1));
            group1.Items.Add(new SampleDataItem("RenderMode",
                  "RenderMode",
                  "Draw PDF pages by Microsoft API.",
                  "Assets/DarkGray.png",
                  "C1PdfViewer supports two different render modes. The default mode renders the document using native XAML elements. This enables some features like text select and search. The new 'System' render mode uses the Windows 8.1 native PDF API that renders each page as an image. The system mode can be reliable for more PDF features, but it lacks text select and search features.",
                  new RenderMode(),
                  group1));
            group1.Items.Add(new SampleDataItem("Thumbnails",
                "Thumbnails",
                "Display thumbnails for a different navigation scenario.",
                "Assets/DarkGray.png",
                "Create a list of page thumbnails using the GetPages method.",
                new Thumbnails(),
                group1));
            group1.Items.Add(new SampleDataItem("PDF Acroform",
                 "PDF Acroform",
                 "Display PDF file which includes acroform elements",
                 "Addets/DarkGray.png",
                 "You can display PDFs which contain acroform elements. When using Default render mode these elements remain interactive.",
                  new AcroformDemo(),
                  group1));
            group1.Items.Add(new SampleDataItem("PDF Annotation",
                "PDF Annotation",
                "Create annotations in the PDF file",
                "Assets/DarkGray.png",
                "The C1PdfViewer can also display some annotation contained in the PDF file.",
                new AnnotationDemo(),
                group1));

            this.AllGroups.Add(group1);
        }
    }
}
