using System;
using System.Collections.Generic;
using System.Linq;
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.Navigation;
using System.Windows.Shapes;
using C1.WPF.DataGrid;
using System.Xml.Serialization;
using System.IO;
using System.Windows.Threading;

namespace DataGrid_SaveState
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        bool doneLoading;
        private DispatcherTimer _saveSettingTimer;

        public MainWindow()
        {
            InitializeComponent();

            
            c1DataGrid1.ColumnReordered += new EventHandler<C1.WPF.DataGrid.DataGridColumnEventArgs>(c1DataGrid1_ColumnReordered);
            c1DataGrid1.SortChanged += new EventHandler<DataGridSortChangedEventArgs>(c1DataGrid1_SortChanged);
            c1DataGrid1.GroupChanged += new EventHandler<DataGridGroupChangedEventArgs>(c1DataGrid1_GroupChanged);
            c1DataGrid1.FilterChanged += new EventHandler<DataGridFilterChangedEventArgs>(c1DataGrid1_FilterChanged);
            c1DataGrid1.FrozenColumnCountChanged += new EventHandler<C1.WPF.PropertyChangedEventArgs<int>>(c1DataGrid1_FrozenColumnCountChanged);
            c1DataGrid1.AutoGeneratedColumns += new EventHandler(c1DataGrid1_AutoGeneratedColumns);

            c1DataGrid1.ItemsSource = Person.Generate(5000);
            doneLoading = true;
            _saveSettingTimer = new DispatcherTimer();
            _saveSettingTimer.Interval = TimeSpan.FromSeconds(0.5);
            _saveSettingTimer.Tick += SaveDataGridSettings;
        }

        void c1DataGrid1_AutoGeneratedColumns(object sender, EventArgs e)
        {
            //c1DataGrid1.Columns["ImageUrl"].DisplayIndex = 0;
            if (HasDataGridSettings())
            {
                var dataGridSettings = GetDataGridSettings();
                c1DataGrid1.FrozenColumnCount = dataGridSettings.FrozenColumnsCount;
                var sortDict = new Dictionary<C1.WPF.DataGrid.DataGridColumn, UserColumnSettings.SortGroupState>();
                var groupDict = new Dictionary<C1.WPF.DataGrid.DataGridColumn, UserColumnSettings.SortGroupState>();
                var filterList = new List<KeyValuePair<C1.WPF.DataGrid.DataGridColumn, DataGridFilterState>>();
                foreach (var columnSetting in dataGridSettings.ColumnSettings)
                {
                    var column = c1DataGrid1.Columns[columnSetting.ColumnName];
                    if (column != null)
                    {
                        column.DisplayIndex = columnSetting.DisplayIndex;
                        sortDict[column] = columnSetting.Sort;
                        groupDict[column] = columnSetting.Group;
                        filterList.Add(new KeyValuePair<C1.WPF.DataGrid.DataGridColumn, C1.WPF.DataGrid.DataGridFilterState>(column, columnSetting.Filter));
                        if (columnSetting.Width > 0)
                        {
                            column.Width = new C1.WPF.DataGrid.DataGridLength(columnSetting.Width);
                        }
                    }
                }
                if (filterList.Count > 0)
                {
                    c1DataGrid1.FilterBy(filterList.ToArray());
                }
                if (sortDict.Count > 0)
                {
                    var sortparam = sortDict.OrderBy(pair => pair.Value.Index).Select(pair => new KeyValuePair<C1.WPF.DataGrid.DataGridColumn, DataGridSortDirection>(pair.Key, pair.Value.Direction)).ToArray();
                    c1DataGrid1.SortBy(sortDict.OrderBy(pair => pair.Value.Index).Select(pair => new KeyValuePair<C1.WPF.DataGrid.DataGridColumn, DataGridSortDirection>(pair.Key, pair.Value.Direction)).ToArray());
                }
                if (groupDict.Count > 0)
                {
                    var groupparam = groupDict.OrderBy(pair => pair.Value.Index).Select(pair => new KeyValuePair<C1.WPF.DataGrid.DataGridColumn, DataGridSortDirection>(pair.Key, pair.Value.Direction)).ToArray();
                    c1DataGrid1.GroupBy(groupDict.OrderBy(pair => pair.Value.Index).Select(pair => new KeyValuePair<C1.WPF.DataGrid.DataGridColumn, DataGridSortDirection>(pair.Key, pair.Value.Direction)).ToArray());
                }
            }
            else
            {
                SaveDataGridSettingsAsync();
            }
            foreach (var column in c1DataGrid1.Columns)
            {
                column.WidthChanged += new EventHandler<C1.WPF.PropertyChangedEventArgs<C1.WPF.DataGrid.DataGridLength>>(column_WidthChanged);
            }
        }

        void column_WidthChanged(object sender, C1.WPF.PropertyChangedEventArgs<C1.WPF.DataGrid.DataGridLength> e)
        {
            SaveDataGridSettingsAsync();
        }

        void c1DataGrid1_FrozenColumnCountChanged(object sender, C1.WPF.PropertyChangedEventArgs<int> e)
        {
            SaveDataGridSettingsAsync();
        }

        void c1DataGrid1_FilterChanged(object sender, DataGridFilterChangedEventArgs e)
        {
            SaveDataGridSettingsAsync();
        }

        void c1DataGrid1_GroupChanged(object sender, DataGridGroupChangedEventArgs e)
        {
            SaveDataGridSettingsAsync();
        }

        void c1DataGrid1_SortChanged(object sender, DataGridSortChangedEventArgs e)
        {
            SaveDataGridSettingsAsync();
        }

        void c1DataGrid1_ColumnReordered(object sender, C1.WPF.DataGrid.DataGridColumnEventArgs e)
        {
            SaveDataGridSettingsAsync();
        }

        private bool HasDataGridSettings()
        {
            return !string.IsNullOrEmpty(Properties.Settings.Default.DataGridSettings);
        }
  

        private void SaveDataGridSettingsAsync()
        {
            if (!doneLoading)
                return;
            _saveSettingTimer.Start();
        }

        void SaveDataGridSettings(object sender, EventArgs e)
        {
            _saveSettingTimer.Stop();
            DataGridSettings settings = new DataGridSettings();

            // get state from grid
            settings.FrozenColumnsCount = c1DataGrid1.FrozenColumnCount;
            foreach (var column in c1DataGrid1.Columns)
            {
                UserColumnSettings columnSetting = new UserColumnSettings();
                columnSetting.ColumnName = column.Name;
                columnSetting.DisplayIndex = column.DisplayIndex;
                columnSetting.Sort = new UserColumnSettings.SortGroupState() { Direction = column.SortState.Direction, Index = column.SortState.Index };
                columnSetting.Group = new UserColumnSettings.SortGroupState() { Direction = column.GroupState.Direction, Index = column.GroupState.Index };
                columnSetting.Filter = column.FilterState;
                columnSetting.Width = column.Width.IsAbsolute ? column.Width.Value : -1;

                settings.ColumnSettings.Add(columnSetting);
            }

            // serialize DataGridSettings class to XML
            XmlSerializer ser = CreateSerializer();
            StringWriter sw = new StringWriter();
            ser.Serialize(sw, settings);

            // save to user settings
            Properties.Settings.Default.DataGridSettings = sw.ToString();

            // save all settings
            Properties.Settings.Default.Save();
        }

        private DataGridSettings GetDataGridSettings()
        {
            StringReader sr = new StringReader(Properties.Settings.Default.DataGridSettings);
            try
            {
                XmlSerializer ser = CreateSerializer();
                return (DataGridSettings)ser.Deserialize(sr);
            }
            catch
            {

            }
            
            return new DataGridSettings();
        }

        private static XmlSerializer CreateSerializer()
        {
            // DataGridComboBoxFilter needs List<object>
            return new XmlSerializer(typeof(DataGridSettings), new[] { typeof(List<object>) });
        }
    }

    public class UserColumnSettings
    {
        public class SortGroupState
        {
            public DataGridSortDirection Direction { get; set; }
            public int Index { get; set; }
        }
        public string ColumnName { get; set; }
        public int DisplayIndex { get; set; }
        public SortGroupState Sort { get; set; }
        public SortGroupState Group { get; set; }
        public DataGridFilterState Filter { get; set; }
        public double Width { get; set; }
    }

    public class DataGridSettings
    {
        public DataGridSettings()
        {
            ColumnSettings = new List<UserColumnSettings>();
        }
        public List<UserColumnSettings> ColumnSettings { get; set; }
        public int FrozenColumnsCount { get; set; }
    }
}
