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.Controls;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;

// 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 ChartSamples.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 : ChartSamples.Common.BindableBase
    {
        private static Uri _baseUri = new Uri("ms-appx:///");

        public SampleDataCommon(String uniqueId, String title, String imagePath, String description)
        {
            this._uniqueId = uniqueId;
            this._title = title;
            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 _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 imagePath, String description, UserControl sample, SampleDataGroup group)
            : base(uniqueId, title, imagePath, description)
        {
            this._sampleStore = sample;
            this._group = group;
        }

        UserControl _sample, _sampleStore = 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); }
        }

        public void LoadSample()
        {
          Sample = _sampleStore;
        }

        public void UnloadSample()
        {
          Sample = null;
        }
    }

    /// <summary>
    /// Generic group data model.
    /// </summary>
    public class SampleDataGroup : SampleDataCommon
    {
        public SampleDataGroup(String uniqueId, String title, String imagePath, String description)
            : base(uniqueId, title, 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 group_Basics = new SampleDataGroup("Group-Basics",
                    "Basics",
                    "Assets/Gallery.png",
                    "Browse basic chart samples that show features like supported chart types, color palettes, data labels and themes.");
            group_Basics.Items.Add(new SampleDataItem("Group-Basics-Item-1",
                    "Chart Type Gallery",
                    "Assets/Gallery.png",
                    "This sample shows all built-in chart types, themes and palettes.",
                    new Gallery(),
                    group_Basics));
            group_Basics.Items.Add(new SampleDataItem("Group-Basics-Item-2",
                      "Dynamic",
                      "Assets/Dynamic.png",
                      "Shows a live dynamic chart which shows updates to the underlying data source.",
                      new Dynamic(),
                      group_Basics));
            group_Basics.Items.Add(new SampleDataItem("Group-Basics-Item-3",
                     "Stacked Plot Areas Horizontal",
                     "Assets/PlotAreaHorizontal.png",
                     "Shows plot areas stacked horizontally.",
                     new PlotAreasHorizontal(),
                     group_Basics));
            group_Basics.Items.Add(new SampleDataItem("Group-Basics-Item-4",
                      "Stacked Plot Areas Vertical",
                      "Assets/PlotAreaVertical.png",
                      "Shows plot areas stacked vertically.",
                      new PlotAreasVertical(),
                      group_Basics));
            this.AllGroups.Add(group_Basics);

            var group_Markers = new SampleDataGroup("Group-Markers",
                    "Labels and Markers",
                    "Assets/Labels.png",
                    "Browse basic chart samples that show features like supported chart types, color palettes, data labels and themes.");
            group_Markers.Items.Add(new SampleDataItem("Group-Markers-Item-1",
                    "Static Labels and Tooltips",
                    "Assets/Labels.png",
                   "This sample shows static labels for data points with percentage values automatically calculated. You can customize the label template to change the appearance.",
                    new Labels(),
                    group_Markers));
            group_Markers.Items.Add(new SampleDataItem("Group-Markers-Item-2",
                      "Line Marker",
                      "Assets/LineMarker.png",
                      "Shows a vertical line marker bound to the X and Y data.",
                      new LineMarker(),
                      group_Markers));
            group_Markers.Items.Add(new SampleDataItem("Group-Markers-Item-3",
                      "Crosshairs",
                      "Assets/Markers.png",
                      "Shows vertical and horizontal markers like crosshairs. Tap or drag your pointer to move the markers.",
                      new Markers(),
                      group_Markers));
            group_Markers.Items.Add(new SampleDataItem("Group-Markers-Item-4",
                     "Pointer Marker",
                     "Assets/PointerMarker.png",
                     "Shows marker moving with the mouse or pointer.",
                     new MouseMarker(),
                     group_Markers));
            this.AllGroups.Add(group_Markers);

            
            var group_Appearance = new SampleDataGroup("Group-Appearance",
                     "Appearance",
                     "Assets/Animation.png",
                     "Browse samples that show animation and custom style features of C1Chart.");
            group_Appearance.Items.Add(new SampleDataItem("Group-Appearance-Item-1",
                    "Load Animation",
                    "Assets/LoadAnimation.png",
                    "Shows built-in animation API for loading new data.",
                    new LoadAnimation(),
                    group_Appearance));
            group_Appearance.Items.Add(new SampleDataItem("Group-Appearance-Item-2",
                    "Pie Animation",
                    "Assets/PieAnimation.png",
                    "Shows a custom pie chart animation. Select a pie slice to see animation.",
                    new PieAnimation(),
                    group_Appearance));
            group_Appearance.Items.Add(new SampleDataItem("Group-Appearance-Item-3",
                    "Custom Animation",
                    "Assets/Animation.png",
                    "Shows how to make a custom animation for column charts.",
                    new Animation(),
                    group_Appearance));
            
            this.AllGroups.Add(group_Appearance);

            var group_Interaction = new SampleDataGroup("Group-Interaction",
                     "Interaction",
                     "Assets/InteractiveChart.png",
                     "Browse samples that show several different ways to add interactive features.");
            group_Interaction.Items.Add(new SampleDataItem("Group-Interaction-Item-1",
                      "InteractiveChart",
                      "Assets/InteractiveChart.png",
                      "Interactive chart which uses built-in zooming and panning features",
                      new InteractiveChart(),
                      group_Interaction));
            group_Interaction.Items.Add(new SampleDataItem("Group-Interaction-Item-2",
                      "Selection",
                      "Assets/Selection.png",
                      "Shows built-in selection for data points.",
                      new Selection(),
                      group_Interaction));
            group_Interaction.Items.Add(new SampleDataItem("Group-Interaction-Item-3",
                    "Interactive Spin",
                    "Assets/InteractiveSpin.png",
                    "Tap a pie slice or slide the pie around to select a data point.",
                    new PieSpin(),
                    group_Interaction));
            group_Interaction.Items.Add(new SampleDataItem("Group-Interaction-Item-4",
                    "Slice Explode",
                    "Assets/Explode.png",
                    "Tap a pie slice to explode it and display a percentage series label.",
                    new PieSliceExplode(),
                    group_Interaction));
            group_Interaction.Items.Add(new SampleDataItem("Group-Interaction-Item-5",
                    "Range Slider",
                    "Assets/AxisRangeSlider.png",
                    "Shows how to create axis range slider.",
                    new AxisRangeSlider(),
                    group_Interaction));

            this.AllGroups.Add(group_Interaction);


            //special
            var group_Special = new SampleDataGroup("Group-Special",
                      "Special Chart Types",
                      "Assets/PolygonPlot.png",
                      "Browse samples that show features specific to one chart type.");
            group_Special.Items.Add(new SampleDataItem("Group-Special-Item-1",
                      "Financial Chart",
                      "Assets/FinancialChart.png",
                      "Shows a financial chart with Two Y-axes.",
                      new FinancialChart(),
                      group_Special));
            group_Special.Items.Add(new SampleDataItem("Group-Special-Item-2",
                    "Bubble",
                    "Assets/Bubble.png",
                    "Shows a bubble chart with a custom color palette made to resemble Olympic medals.",
                    new Bubble(),
                    group_Special));
            group_Special.Items.Add(new SampleDataItem("Group-Special-Item-3",
                    "Radar",
                    "Assets/Radar.png",
                    "Shows a basic radar chart with support for any number of axis spokes (x values).",
                    new Radar(),
                    group_Special));
            group_Special.Items.Add(new SampleDataItem("Group-Special-Item-4",
                    "Range Columns",
                    "Assets/RangeColumns.png",
                    "Shows a range column series using the Gantt chart type.",
                    new RangeColumnSeries(),
                    group_Special));
            group_Special.Items.Add(new SampleDataItem("Group-Special-Item-5",
                    "Stacked Pie",
                    "Assets/StackedPie.png",
                    "Shows a stacked pie chart loading data from a CSV file.",
                    new StackedPie(),
                    group_Special));
            group_Special.Items.Add(new SampleDataItem("Group-Special-Item-6",
                      "PolygonPlot",
                      "Assets/PolygonPlot.png",
                      "Shows a polygon chart with multiple series.",
                      new PolygonPlot(),
                      group_Special));
            group_Special.Items.Add(new SampleDataItem("Group-Special-Item-7",
                      "Complex Chart",
                      "Assets/ComplexChart.png",
                      "Shows a complex stacked chart with different data series.",
                      new ComplexChart(),
                      group_Special));
            this.AllGroups.Add(group_Special);

           

            var group_Aggregate = new SampleDataGroup("Group-Aggregate",
                "Grouping & Aggregation",
                "Assets/AggregateChart.png",
                "C1Chart supports several scenarios for built-in grouping and aggregation.");
            group_Aggregate.Items.Add(new SampleDataItem("Group-Aggregate-Item-1",
                      "Series Aggregation",
                      "Assets/AggregateChart.png",
                      "By setting one property you can aggregate each data series by sum, count, average and more.",
                      new AggregateChart(),
                      group_Aggregate));
            group_Aggregate.Items.Add(new SampleDataItem("Group-Aggregate-Item-2",
                "Date Axis",
                "Assets/DateAxis.png",
                "Group data along the x-axis by a selected time range (week, month, quarter or year).",
                new DateAxis(),
                group_Aggregate));
            group_Aggregate.Items.Add(new SampleDataItem("Group-Aggregate-Item-3",
                "Group by Name",
                "Assets/AggregateByName.png",
                "Aggregate items for each category name.",
                new AggregateByName(),
                group_Aggregate));
            group_Aggregate.Items.Add(new SampleDataItem("Group-Aggregate-Item-4",
                "Group by Range",
                "Assets/AggregateByRange.png",
                "This sample shows how you can use grouping and aggregation to achieve a distribution chart. This chart counts the number of items that fall into each value range.",
                new AggregateByRange(),
                group_Aggregate));
            this.AllGroups.Add(group_Aggregate);

            var group_Performance = new SampleDataGroup("Group-Performance",
                     "Performance",
                     "Assets/Dynamic.png",
                     "Browse samples that show performance scenarios such as fast rendering modes.");
            group_Performance.Items.Add(new SampleDataItem("Group-Performance-Item-2",
                      "DirectX Rendering",
                      "Assets/ChartDx.png",
                      "High performance chart rendered via Direct2D render mode.",
                      new ChartDx(),
                      group_Performance));

            this.AllGroups.Add(group_Performance);


            
        }
    }
}
