using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using C1.Silverlight;
using C1.Silverlight.FlexGrid;

namespace ColumnPicker
{
    public partial class MainPage : UserControl
    {
        C1ContextMenu ctxMenu = null;
        public MainPage()
        {
            InitializeComponent();

            // populate grid
            _flex.ItemsSource = Product.GetProducts(100);

            // set clipboard copy/paste mode
            _flex.ClipboardCopyMode = ClipboardCopyMode.ExcludeHeader;
            _flex.ClipboardPasteMode = ClipboardCopyMode.ExcludeHeader;

            // set up event handlers for context menu
            _flex.MouseRightButtonDown += (s, e) =>
            {
                e.Handled = true; // << disable standard "Silverlight" menu
            };
            _flex.MouseRightButtonUp += (s, e) =>
            {
                e.Handled = true;
                ShowContextMenu(e);
            };

            // load column layout persisted from previous session, if any
            var layoutFileName = "ColumnLayout.xml";
            var stg = System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplication();
            if (stg != null)
            {
                if (stg.FileExists(layoutFileName))
                {
                    using (var sr = new StreamReader(stg.OpenFile(layoutFileName, FileMode.Open)))
                    {
                        _flex.ColumnLayout = sr.ReadToEnd();
                    }
                }
            }

            // save column layout when application exits
            Application.Current.Exit += (s, e) =>
                {
                    if (stg != null)
                    {
                        using (var sw = new StreamWriter(stg.OpenFile(layoutFileName, FileMode.Create)))
                        {
                            sw.Write(_flex.ColumnLayout);
                        }
                    }
                };

            // save current layout so user can restore whenever he wants to
            _columnLayout = _flex.ColumnLayout;
        }

        // show the context menu
        void ShowContextMenu(MouseEventArgs e)
        {
            // create context menu
            if (ctxMenu != null && ctxMenu.Visibility == System.Windows.Visibility.Visible)
            {
                ctxMenu.Hide();
            }
            ctxMenu = new C1ContextMenu() { AutoClose = false };

            // check what type of cell was clicked to show the right menu
            var ht = _flex.HitTest(e);
            switch (ht.CellType)
            {
                // if the click was on the column headers, show column picker
                case CellType.ColumnHeader:
                    CreateColumnPickerMenu(ctxMenu);
                    break;

                // show clipboard menu if the click was on a regular cell
                case CellType.Cell:

                    // select cell if not yet selected
                    if (!_flex.Selection.Contains(ht.CellRange))
                    {
                        _flex.Select(ht.CellRange, false);
                    }
                    CreateClipboardMenu(ctxMenu);
                    break;
            }

            // show the menu
            var pt = e.GetPosition(LayoutRoot);
            Point offset = new Point(pt.X, pt.Y);
            ctxMenu.InvalidateMeasure();
            ctxMenu.InvalidateArrange();
            ctxMenu.Show(LayoutRoot, offset);
        }

        // populate context menu with column picker
        void CreateColumnPickerMenu(C1ContextMenu ctxMenu)
        {
            foreach (var c in _flex.Columns)
            {
                // create checkbox to represent this column
                var chk = new CheckBox();
                chk.Tag = c;
                chk.IsChecked = c.Visible;
                chk.Content = !string.IsNullOrEmpty(c.Header)
                    ? c.Header
                    : c.BoundPropertyName;

                // create menu item to hold the checkbox
                var mi = new C1MenuItem();
                mi.Header = chk;
                ctxMenu.Items.Add(mi);

                // toggle column visibility when checkbox is clicked
                chk.Click += (s, ea) =>
                {
                    var col = chk.Tag as Column;
                    col.Visible = chk.IsChecked.Value;
                    ctxMenu.Hide();
                };
            }
        }

        // populate context menu with clipboard commands
        void CreateClipboardMenu(C1ContextMenu ctxMenu)
        {
            foreach (string cmd in "Cut|Copy|Paste|Delete".Split('|'))
            {
                // create menu item to hold the command
                var mi = new C1MenuItem();
                mi.Header = cmd;
                ctxMenu.Items.Add(mi);

                // execute commands
                mi.Click += (s, ea) =>
                {
                    switch ((string)mi.Header)
                    {
                        case "Cut":
                            _flex.Copy();
                            foreach (var cell in _flex.Selection.Cells)
                            {
                                _flex[cell.Row, cell.Column] = null;
                            }
                            break;

                        case "Copy":
                            _flex.Copy();
                            break;

                        case "Paste":
                            _flex.Paste();
                            break;

                        case "Delete":
                            foreach (var cell in _flex.Selection.Cells)
                            {
                                _flex[cell.Row, cell.Column] = null;
                            }
                            break;
                    }

                    // done, close the menu
                    ctxMenu.Hide();
                };
            }
        }

        // use the ColumnLayout to save/restore column layout
        // the ColumnLayout property gets/sets an XML string that contains the 
        // order, visibility, and width of the columns on the grid.
        string _columnLayout;
        void SaveLayout_Click(object sender, RoutedEventArgs e)
        {
            _columnLayout = _flex.ColumnLayout;
        }
        void LoadLayout_Click(object sender, RoutedEventArgs e)
        {
            _flex.ColumnLayout = _columnLayout;
        }
    }
}
