using System.ComponentModel;
using C1.Silverlight.FlexGrid;
using C1.Silverlight.FlexGridExcel;
using System.Collections.Generic;

namespace ExcelGrid
{
    /// <summary>
    /// Undoable group action which records the grouping state.
    /// </summary>
    public class GroupAction : IUndoableAction
    {
        //-------------------------------------------------------------------------
        #region ** fields

        C1FlexGrid _flex;
        GroupDescription[] _oldGroupDescriptions;
        GroupDescription[] _newGroupDescriptions;
        Dictionary<string, bool> _oldColumnVisibilities;
        Dictionary<string, bool> _newColumnVisibilities;

        #endregion

        //-------------------------------------------------------------------------
        #region ** object model

        public void RecordUndoState()
        {
            RecordState(ref _oldGroupDescriptions, _oldColumnVisibilities);
        }

        public void RecordRedoState()
        {
            RecordState(ref _newGroupDescriptions, _newColumnVisibilities);
        }

        #endregion

        //-------------------------------------------------------------------------
        #region ** ctor

        /// <summary>
        /// Initializes a new instance of an <see cref="GroupAction"/>.
        /// <param name="sender"><see cref="C1FlexGrid"/> that owns the action.</param>
        /// </summary>
        public GroupAction(object sender)
        {
            _flex = sender as C1FlexGrid;
            _oldColumnVisibilities = new Dictionary<string, bool>();
            _newColumnVisibilities = new Dictionary<string, bool>();
        }

        #endregion

        //-------------------------------------------------------------------------
        #region ** IUndoableAction

        public void Undo()
        {
            SetGroupDescriptions(_oldGroupDescriptions);
            SetVisibilities(_oldColumnVisibilities);
        }
        public void Redo()
        {
            SetGroupDescriptions(_newGroupDescriptions);
            SetVisibilities(_newColumnVisibilities);
        }

        #endregion

        //-------------------------------------------------------------------------
        #region ** implementation

        /// <summary>
        /// Records the current grouping and column visibility state of the <see cref="C1FlexGrid"/>.
        /// </summary>
        /// <param name="groupDescriptions">Array used to store the group descriptions values at the moment the method is invoked.</param>
        /// <param name="columnVisibilities">Dictionary used to store the column visibilities at the moment the method is invoked.</param>
        void RecordState(ref GroupDescription[] groupDescriptions, Dictionary<string, bool> columnVisibilities)
        {
            groupDescriptions = new GroupDescription[_flex.CollectionView.GroupDescriptions.Count];
            _flex.CollectionView.GroupDescriptions.CopyTo(groupDescriptions, 0);
            columnVisibilities.Clear();
            foreach (var col in _flex.Columns)
            {
                columnVisibilities[col.ColumnName] = col.Visible;
            }
        }

        void SetGroupDescriptions(GroupDescription[] groupDescriptions)
        {
            if (_flex.CollectionView != null && _flex.CollectionView.CanGroup)
            {
                using (_flex.CollectionView.DeferRefresh())
                {
                    _flex.CollectionView.GroupDescriptions.Clear();
                    for (int i = 0; i < groupDescriptions.Length; i++)
                    {
                        _flex.CollectionView.GroupDescriptions.Add(groupDescriptions[i]);
                    }
                }
            }
        }

        void SetVisibilities(Dictionary<string, bool> columnVisibilities)
        {
            foreach (var colVisibility in columnVisibilities)
            {
                _flex.Columns[colVisibility.Key].Visible = colVisibility.Value;
            }
        }

        #endregion
    }
}