using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using System.ComponentModel;
using System.Collections.Generic;
using C1.Silverlight.FlexGrid;

namespace C1.Silverlight.FlexGridExcel
{
    internal class SortCellFactory : CellFactory
    {
        // ** fields
        C1FlexGrid _owner;
        static ListSortDirection[] _sortDirections = new ListSortDirection[] 
        { 
            ListSortDirection.Ascending, 
            ListSortDirection.Descending 
        };
        const int MAX_DROPDOWN_HEIGHT = 120;

        // ** ctor
        public SortCellFactory(C1FlexGrid owner)
        {
            _owner = owner;
        }

        // create cell content to show property name or sort direction
        public override void CreateCellContent(C1FlexGrid grid, Border bdr, CellRange range)
        {
            var col = grid.Columns[range.Column];
            switch (col.BoundPropertyName)
            {
                case "PropertyName":
                    bdr.Child = CreatePropertyCell(grid, bdr, range);
                    return;
                case "Direction":
                    bdr.Child = CreateDirectionCell(grid, bdr, range);
                    return;
            }
            throw new Exception("unexpected column");
        }

        // cell that shows the property name
        FrameworkElement CreatePropertyCell(C1FlexGrid grid, Border bdr, CellRange range)
        {
            // create layout grid
            var g = new Grid();
            g.ColumnDefinitions.Add(new ColumnDefinition());
            g.ColumnDefinitions.Add(new ColumnDefinition());
            g.ColumnDefinitions[0].Width = new GridLength(1, GridUnitType.Star);
            g.ColumnDefinitions[1].Width = new GridLength(2.5, GridUnitType.Star);

            // cell title
            var t = new TextBlock();
            t.MouseLeftButtonDown += t_MouseLeftButtonDown;
            t.VerticalAlignment = VerticalAlignment.Center;
            t.Text = range.Row == 0 ? "Sort By" : "Then By";
            g.Children.Add(t);

            // property name combo
            var cb = new ComboBox();
            cb.MaxDropDownHeight = MAX_DROPDOWN_HEIGHT;
            cb.DropDownClosed += cb_DropDownClosed;
            cb.ItemsSource = _owner.Columns;
            cb.DisplayMemberPath = "Binding.Path.Path";// "BoundPropertyName";
            cb.SelectedValuePath = cb.DisplayMemberPath;
            cb.SetValue(Grid.ColumnProperty, 1);
            g.Children.Add(cb);

            // bind SelectedValue to PropertyName property
            var b = new Binding("PropertyName");
            b.Mode = BindingMode.TwoWay;
            cb.SetBinding(ComboBox.SelectedValueProperty, b);

            // done
            return g;
        }

        // cell that shows the sort direction
        FrameworkElement CreateDirectionCell(C1FlexGrid grid, Border bdr, CellRange range)
        {
            // sort direction combo
            var cb = new ComboBox();
            cb.MaxDropDownHeight = MAX_DROPDOWN_HEIGHT;
            cb.DropDownClosed += cb_DropDownClosed;
            cb.ItemsSource = _sortDirections;

            // bind SelectedValue to SortDirection property
            var b = new Binding("Direction");
            b.Mode = BindingMode.TwoWay;
            cb.SetBinding(ComboBox.SelectedItemProperty, b);

            // done
            return cb;
        }

        // select item when TextBlock is clicked or when combo closes
        void t_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            SelectItem(sender);
        }
        void cb_DropDownClosed(object sender, EventArgs e)
        {
            SelectItem(sender);
        }
        void SelectItem(object sender)
        {
            var e = sender as FrameworkElement;
            for (var p = e; p != null; )
            {
                p = VisualTreeHelper.GetParent(p) as FrameworkElement;
                var flex = p as C1FlexGrid;
                if (flex != null)
                {
                    flex.SelectedItem = e.DataContext;
                    break;
                }
            }
        }
    }
}
