using System;
using System.Net;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Data;
using System.Windows.Media.Imaging;
using System.Collections.Generic;
using System.Windows.Markup;
using System.ComponentModel;
using Telerik.Windows;
using Telerik.Windows.Data;
using Telerik.Windows.Controls;
using Telerik.Windows.Controls.GridView;

namespace SilverlightGrid
{
    public class GridViewHeaderMenu
    {
        private RadGridView grid = null;

        public GridViewHeaderMenu(RadGridView grid)
        {
            this.grid = grid;
        }

        public static readonly DependencyProperty IsEnabledProperty
            = DependencyProperty.RegisterAttached("IsEnabled", typeof(bool), typeof(GridViewHeaderMenu),
                new System.Windows.PropertyMetadata(new PropertyChangedCallback(OnIsEnabledPropertyChanged)));

        public static void SetIsEnabled(DependencyObject dependencyObject, bool enabled)
        {
            dependencyObject.SetValue(IsEnabledProperty, enabled);
        }

        public static bool GetIsEnabled(DependencyObject dependencyObject)
        {
            return (bool)dependencyObject.GetValue(IsEnabledProperty);
        }

        private static void OnIsEnabledPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            RadGridView grid = dependencyObject as RadGridView;
            if (grid != null)
            {
                if ((bool) e.NewValue)
                {
                    if (grid.IsFilteringAllowed)
                    {
                        // Create new GridViewHeaderMenu and attach RowLoaded event.
                        GridViewHeaderMenu menu = new GridViewHeaderMenu(grid);
                        menu.Attach();
                    }
                }
            }
        }

        private void Attach()
        {
            if (grid != null)
            {
                grid.RowLoaded += new EventHandler<RowLoadedEventArgs>(RowLoaded);
            }
        }

        private void RowLoaded(object sender, RowLoadedEventArgs e)
        {
            if (e.Row is GridViewHeaderRow)
            {
                InitializeMenus((GridViewHeaderRow) e.Row);
            }
        }

        private void InitializeMenus(GridViewHeaderRow row)
        {
            IEnumerable<GridViewHeaderCell> cells = row.Cells.OfType<GridViewHeaderCell>();

            foreach (GridViewHeaderCell cell in cells)
            {
                // create menu
                RadContextMenu contextMenu = new RadContextMenu();
                // set menu Theme
                StyleManager.SetTheme(contextMenu, StyleManager.GetTheme(grid));

                RadMenuItem item = new RadMenuItem() { Header = String.Format(@"Sort Ascending by ""{0}""", cell.Column.HeaderText) };
                contextMenu.Items.Add(item);

                item = new RadMenuItem() { Header = String.Format(@"Sort Descending by ""{0}""", cell.Column.HeaderText) };
                contextMenu.Items.Add(item);

                item = new RadMenuItem() { Header = String.Format(@"Clear Sorting by ""{0}""", cell.Column.HeaderText) };
                contextMenu.Items.Add(item);

                item = new RadMenuItem() { Header = String.Format(@"Group by ""{0}""", cell.Column.HeaderText) };
                contextMenu.Items.Add(item);

                item = new RadMenuItem() { Header = String.Format(@"Ungroup ""{0}""", cell.Column.HeaderText) };
                contextMenu.Items.Add(item);

                item = new RadMenuItem() { Header = "Choose Columns:" };
                contextMenu.Items.Add(item);

                // create menu items
                foreach (GridViewColumn column in grid.Columns)
                {
                    RadMenuItem subMenu = new RadMenuItem()
                    {
                        Header = column.HeaderText,
                        IsCheckable = true,
                        IsChecked = true
                    };

                    // bind IsChecked menu item property to IsVisible column property
                    subMenu.SetBinding(RadMenuItem.IsCheckedProperty,
                        new Binding("IsVisible") { Mode = BindingMode.TwoWay, Source = column });

                    item.Items.Add(subMenu);
                }

                contextMenu.AddHandler(RadMenuItem.ClickEvent, new RoutedEventHandler(OnMenuItemClick));

                // attach menu
                RadContextMenu.SetContextMenu(cell, contextMenu);
            }
        }

        void OnMenuItemClick(object sender, RoutedEventArgs e)
        {
            RadContextMenu menu = (RadContextMenu) sender;
            RadMenuItem clickedItem = ((RadRoutedEventArgs) e).OriginalSource as RadMenuItem;
            GridViewColumn column = ((GridViewHeaderCell) menu.UIElement).Column;

            if (clickedItem.Parent is RadMenuItem)
                return;

            string header = Convert.ToString(clickedItem.Header);

            SortDescription sd = (from d in grid.SortDescriptions
                                     where d.PropertyName == column.UniqueName
                                     select d).FirstOrDefault();

            if (header.Contains("Sort Ascending"))
            {
                if (sd.PropertyName != null)
                {
                    grid.SortDescriptions.Remove(sd);
                }

                grid.SortDescriptions.Add(new SortDescription(column.UniqueName,
                    ListSortDirection.Ascending));
            }
            else if (header.Contains("Sort Descending"))
            {
                if (sd.PropertyName != null)
                {
                    grid.SortDescriptions.Remove(sd);
                }

                grid.SortDescriptions.Add(new SortDescription(column.UniqueName,
                    ListSortDirection.Descending));
            }
            else if (header.Contains("Clear Sorting"))
            {
                if (sd.PropertyName != null)
                {
                    grid.SortDescriptions.Remove(sd);
                }
            }
            else if (header.Contains("Group by"))
            {
                RadGroupDescription gd = (from d in grid.GroupDescriptions
                                      where d.PropertyName == column.UniqueName
                                      select d).FirstOrDefault();
                
                if (gd == null)
                {
                    grid.GroupDescriptions.Add(new RadGroupDescription(column.UniqueName));
                }
            }
            else if (header.Contains("Ungroup"))
            {
                RadGroupDescription gd = (from d in grid.GroupDescriptions
                                          where d.PropertyName == column.UniqueName
                                          select d).FirstOrDefault();
                if (gd != null)
                {
                    grid.GroupDescriptions.Remove(gd);
                }
            }
        }
    }
}
