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

// 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 FlexGridSamples.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 : FlexGridSamples.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;
        }

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

        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._sample = sample;
            this._group = group;
        }

        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()
        {
            String ITEM_CONTENT = String.Format("Item Content: {0}\n\n{0}\n\n{0}\n\n{0}\n\n{0}\n\n{0}\n\n{0}",
                        "Curabitur class aliquam vestibulum nam curae maecenas sed integer cras phasellus suspendisse quisque donec dis praesent accumsan bibendum pellentesque condimentum adipiscing etiam consequat vivamus dictumst aliquam duis convallis scelerisque est parturient ullamcorper aliquet fusce suspendisse nunc hac eleifend amet blandit facilisi condimentum commodo scelerisque faucibus aenean ullamcorper ante mauris dignissim consectetuer nullam lorem vestibulum habitant conubia elementum pellentesque morbi facilisis arcu sollicitudin diam cubilia aptent vestibulum auctor eget dapibus pellentesque inceptos leo egestas interdum nulla consectetuer suspendisse adipiscing pellentesque proin lobortis sollicitudin augue elit mus congue fermentum parturient fringilla euismod feugiat");

            var group1 = new SampleDataGroup("Group-1",
                    "All Samples",
                    "Group Subtitle: 1",
                    "Assets/Financial.png",
                    "C1FlexGrid is a DataGrid control with a lightweight, flexible object model. C1FlexGrid offers many unique features such as unbound mode, sorting, filtering, flexible cell merging, and multi-cell row and column headers.");
            group1.Items.Add(new SampleDataItem("Financial",
                    "See it in action!",
                    "",
                    "Assets/Financial.png",
                    "C1FlexGrid is a DataGrid control with a lightweight, flexible object model. C1FlexGrid offers many unique features such as unbound mode, sorting, filtering, flexible cell merging, and multi-cell row and column headers.",
                    new Financial(),
                    group1));
            group1.Items.Add(new SampleDataItem("CollectionView",
                    "Sort, Filter, Group",
                    "",
                    "Assets/CollectionView.png",
                    "FlexGrid supports C1CollectionView to provide live sorting, filtering and grouping, the features absent in the native CollectionViewSource/ICollectionView implementation. Tap a column header once or twice to sort that column.",
                    new CollectionView(),
                    group1));
            group1.Items.Add(new SampleDataItem("Media Library",
                    "Custom Cells",
                    "",
                    "Assets/itunes.png",
                    "This demo showcases the C1FlexGrid&#39;s CellFactory interface used for customizing cells. We use custom cells to display images next to the artists, albums, songs, collapse/expand icons, and ratings. We can easily create custom cells by inheriting the ICellFactory interface and providing the FrameworkElement objects used to represent the cells.",
                    new MediaLibrary(),
                    group1));
            
            group1.Items.Add(new SampleDataItem("Editing",
                    "Editing",
                    "",
                    "Assets/Editing.png",
                    "The C1FlexGrid control supports Excel-style editing. Just type values into cells and use the enter or arrow keys to move to the next one. Or press F2 and enter full-edit mode, where arrow keys navigate within the editor. Auto-complete and value-mapped columns are also built-in: simply create a ColumnValueConverter and assign it to the columns ValueConverter property and you're done. Transactioned edits are supported too. The Customer class used here implements IEditableObject, so you can undo changes by pressing the Escape key before you move to a new row. (Note: the gray columns are read-only). Note this feature is only supported by mouse and keyboard.",
                    new Editing(),
                    group1));
            group1.Items.Add(new SampleDataItem("Unbound",
                    "Unbound",
                    "",
                    "Assets/Unbound.png",
                    "In addition to working with IEnumerable data sources, the C1FlexGrid also supports an unbound mode, where cell values are stored in the grid itself and are accessed using familiar indexing notation. This demo also shows how you can set up merged multi-cell row and column headers.",
                    new Unbound(),
                    group1));
            group1.Items.Add(new SampleDataItem("CustomColumns",
                    "Custom Columns",
                    "",
                    "Assets/CustomColumns.png",
                    "The sample shows how you can combine custom columns with regular bound columns. All custom columns are implemented in XAML using the Column.CellTemplate property.",
                    new CustomColumns(),
                    group1));
            group1.Items.Add(new SampleDataItem("Cell Merging",
                    "Cell Merging",
                    "",
                    "Assets/CellMerging.png",
                    "Merge adjacent cells by mouse (touch support coming soon!)",
                    new ExcelStyleMerge(),
                    group1));
            group1.Items.Add(new SampleDataItem("Printing",
                    "Printing",
                    "",
                    "Assets/Printing.png",
                    "Directly output your FlexGrid UI to any printer. The C1FlexGrid control provides a GetPageImages method that beaks up the grid into a list of Visual Elements representing each page in a document which allows for printing.",
                    new Printing(),
                    group1));
            //group1.Items.Add(new SampleDataItem("YouTube",
            //        "Incremental Loading",
            //        "",
            //        "Assets/YouTube.png",
            //        "Diplays a list of YouTube videos which load on demand when the end of the list is reached.",
            //        new YouTube(),
            //        group1));
            group1.Items.Add(new SampleDataItem("Drag-drop Rows and Columns",
                   "Drag-drop Rows and Columns",
                   "",
                   "Assets/DragDropRows.png",
                   "The sample shows drag-drop rows and columns when FlexGrid is in unbound mode.Press and hold a row header/column header until it becomes selected. Then drag the row header/column header to the desired location.",
                   new FlexGridSamples.View.DragDropRows(),
                   group1));
            this.AllGroups.Add(group1);
        }
    }
}
