// Window1.xaml.cs
using System;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Diagnostics;
using System.ComponentModel; // INotifyPropertyChanged
using System.Collections.ObjectModel; // ObserverableCollection<T>
using System.Collections;

namespace ListBinding2 {

  public class Person : INotifyPropertyChanged {
    // INotifyPropertyChanged Members
    public event PropertyChangedEventHandler PropertyChanged;
    protected void Notify(string propName) {
      if( this.PropertyChanged != null ) {
        PropertyChanged(this, new PropertyChangedEventArgs(propName));
      }
    }

    string name;
    public string Name {
      get { return this.name; }
      set {
        if( this.name == value ) { return; }
        this.name = value;
        Notify("Name");
      }
    }

    int age;
    public int Age {
      get { return this.age; }
      set {
        if( this.age == value ) { return; }
        this.age = value;
        Notify("Age");
      }
    }

    public Person() { }
    public Person(string name, int age) {
      this.name = name;
      this.age = age;
    }
  }

  //class People : List<Person> { }
  class People : ObservableCollection<Person> { }

  public partial class Window1 : Window {

    public Window1() {
      InitializeComponent();

      this.birthdayButton.Click += birthdayButton_Click;
      this.backButton.Click += backButton_Click;
      this.forwardButton.Click += forwardButton_Click;
      this.addButton.Click += addButton_Click;
      this.sortButton.Click += sortButton_Click;
      this.filterButton.Click += filterButton_Click;
      this.groupButton.Click += groupButton_Click;
    }

    ICollectionView GetFamilyView() {
      People people = (People)this.FindResource("Family");
      return CollectionViewSource.GetDefaultView(people);
    }

    void birthdayButton_Click(object sender, RoutedEventArgs e) {
      ICollectionView view = GetFamilyView();
      Person person = (Person)view.CurrentItem;

      ++person.Age;
      MessageBox.Show(
        string.Format(
          "Happy Birthday, {0}, age {1}!",
          person.Name,
          person.Age),
        "Birthday");
    }

    void backButton_Click(object sender, RoutedEventArgs e) {
      ICollectionView view = GetFamilyView();
      view.MoveCurrentToPrevious();
      if( view.IsCurrentBeforeFirst ) {
        view.MoveCurrentToFirst();
      }
    }

    void forwardButton_Click(object sender, RoutedEventArgs e) {
      ICollectionView view = GetFamilyView();
      view.MoveCurrentToNext();
      if( view.IsCurrentAfterLast ) {
        view.MoveCurrentToLast();
      }
    }

    void addButton_Click(object sender, RoutedEventArgs e) {
      People people = (People)this.FindResource("Family");
      people.Add(new Person("Chris", 37));
    }

    class PersonSorter : IComparer {
      public int Compare(object x, object y) {
        Person lhs = (Person)x;
        Person rhs = (Person)y;

        // Sort Name ascending and Age descending
        int nameCompare = lhs.Name.CompareTo(rhs.Name);
        if( nameCompare != 0 )
          return nameCompare;
        return rhs.Age - lhs.Age;
      }
    }

    void sortButton_Click(object sender, RoutedEventArgs e) {
      //ICollectionView view = GetFamilyView();
      //if( view.SortDescriptions.Count == 0 ) {
      //  view.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending));
      //  view.SortDescriptions.Add(new SortDescription("Age", ListSortDirection.Descending));
      //}
      //else {
      //  view.SortDescriptions.Clear();
      //}

      ListCollectionView view = (ListCollectionView)GetFamilyView();
      if( view.CustomSort == null ) {
        view.CustomSort = new PersonSorter();
      }
      else {
        view.CustomSort = null;
      }
    }

    void filterButton_Click(object sender, RoutedEventArgs e) {
      ICollectionView view = GetFamilyView();
      if( view.Filter == null ) {
        view.Filter = delegate(object item) {
          // Just show the over 25-year olds
          return ((Person)item).Age >= 25;
        };
      }
      else {
        view.Filter = null;
      }
    }

    void groupButton_Click(object sender, RoutedEventArgs e) {
      ICollectionView view = GetFamilyView();
      if( view.GroupDescriptions.Count == 0 ) {
        // Group by range, then age
        view.GroupDescriptions.Add(new PropertyGroupDescription("Age", new AgeToRangeConverter()));
        //view.GroupDescriptions.Add(new PropertyGroupDescription("Age", new AgeToAllRangeConverter()));
        //view.GroupDescriptions.Add(new PropertyGroupDescription(null, new PersonToRangeConverter()));
        view.GroupDescriptions.Add(new PropertyGroupDescription("Age"));
      }
      else {
        view.GroupDescriptions.Clear();
      }

    }

    void showButton_Click(object sender, RoutedEventArgs e) {
      // get the button generated by the data template expansion
      Button showButton = (Button)sender;

      // get the person associated with the generated button via the data context
      Person person = (Person)showButton.DataContext;

      // do something with that person...
      MessageBox.Show(string.Format("{0} is {1} years old", person.Name, person.Age));
    }

  }

  public class AgeToForegroundConverter : IValueConverter {
    // Called when converting the Age to a Foreground brush
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
      Debug.Assert(targetType == typeof(Brush));

      // DANGER! After 25, it's all down hill...
      int age = int.Parse(value.ToString());
      return (age > 25 ? Brushes.Red : Brushes.Black);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
      // should not be called in our example
      throw new NotImplementedException();
    }
  }

  public class AgeToRangeConverter : IValueConverter {
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
      return (int)value < 25 ? "Under the Hill" : "Over the Hill";
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
      // should not be called in our example
      throw new NotImplementedException();
    }
  }

  public class AgeToAllRangeConverter : IValueConverter {
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
      return new string[] { "Under the Hill", "Over the Hill" };
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
      // should not be called in our example
      throw new NotImplementedException();
    }
  }

  public class PersonToRangeConverter : IValueConverter {
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
      return ((Person)value).Age < 25 ? "Under the Hill" : "Over the Hill";
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
      // should not be called in our example
      throw new NotImplementedException();
    }
  }

}
