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;

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

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

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

        public string Name { get; set; }

        public DataTemplate Icon
        {
            get
            {
                try
                {
                    return (DataTemplate)App.Current.Resources["IconC1" + Name.Replace(" ", "")];
                }
                catch
                {
                    return (DataTemplate)App.Current.Resources["IconC1Gray"];
                }
        }
        }

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

        public override string ToString()
        {
            return this.Title;
        }
    }

    /// <summary>
    /// Generic item data model.
    /// </summary>
    public class SampleDataItem : SampleDataCommon
    {
        public SampleDataItem(String uniqueId, String title, String description, String imagePath, Type pageType)
            : base(uniqueId, title, description, imagePath)
        {
            _pageType = pageType;
        }

        private Type _pageType;
        public Type PageType
        {
            get { return this._pageType; }
            set { this.SetProperty(ref this._pageType, value); }
        }
    }

    /// <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<SampleDataItem> _allItems = new ObservableCollection<SampleDataItem>();
        public ObservableCollection<SampleDataItem> AllItems
        {
            get { return this._allItems; }
        }

        public static IEnumerable<SampleDataItem> GetItems(string uniqueId)
        {
            if (!uniqueId.Equals("AllItems")) throw new ArgumentException("Only 'AllItems' is supported as a collection of items");

            return _sampleDataSource.AllItems;
        }

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


        public SampleDataSource()
        {
            _allItems.Add(new SampleDataItem("DemoMaps",
                    "Basic Demo",
                    "Get smooth zooming, panning, and mapping between screen and geographical coordinates with C1Maps. Display information from various sources, including Microsoft Live Maps. You can even superimpose your own custom elements to the maps.",
                    "Assets/LightGray.png",
                    typeof(DemoMaps)));
            _allItems.Add(new SampleDataItem("CustomTileSource",
                    "Custom Source",
                    "Shows that you can implement new image sources such as using OpenStreetMap.",
                    "Assets/LightGray.png",
                    typeof(CustomTileSource)));
            _allItems.Add(new SampleDataItem("Cities",
                    "Cities Demo",
                    "Using the vector layer, this map shows the largest cities of the world (by population).",
                    "Assets/LightGray.png",
                    typeof(Cities)));
            _allItems.Add(new SampleDataItem("EarthQuake",
                    "Earthquakes Demo",
                    "Shows Earthquake data by adding various vector data on the map.",
                    "Assets/LightGray.png",
                    typeof(EarthQuake)));
            _allItems.Add(new SampleDataItem("Flicker",
                    "Flickr Demo",
                    "Displays images from a GeoRSS reader using Flickr.",
                    "Assets/LightGray.png",
                    typeof(Flicker)));
            _allItems.Add(new SampleDataItem("Grid",
                    "Gridlines",
                    "The vector layer allows you to add parallels and meridians to the map. You can use the vector layer on top of a Tile Source to draw geometries/shapes/polygons/paths with geo coordinates.",
                    "Assets/LightGray.png",
                    typeof(MapsSamples.Grid)));
            _allItems.Add(new SampleDataItem("MapChart",
                    "KML/KMZ",
                    "Shows how you can create a map chart based on country polygons loaded from KMZ file (zipped KML) into a C1VectorLayer. It also shows that you can use a C1Maps without any Tile Source.",
                    "Assets/LightGray.png",
                    typeof(MapChart)));
            _allItems.Add(new SampleDataItem("Marks",
                    "Add Marks",
                    "Shows how you can dynamically add marks to the map control.",
                    "Assets/LightGray.png",
                    typeof(Marks)));
            _allItems.Add(new SampleDataItem("Factories",
                    "Virtualization",
                    "Shows how you can use the VirtualLayer to display elements on C1Maps using data virtualization. Map items are not loaded into memory until brought into view.",
                    "Assert/LightGray.png",
                    typeof(Factories)));
            _allItems.Add(new SampleDataItem("MapShape",
                    "Shape Files",
                    "Shows how you can display a map based on polygons loaded from a Shape File (shp).",
                    "Assert/LightGray.png",
                    typeof(MapShape)));
        }
    }
}
