using System;
using System.Collections.Generic;
using System.Web;
using Telerik.Web.UI;
using System.Web.UI.WebControls;
using System.Collections;
using System.Web.UI;
using System.IO;

/// <summary>
/// Imports and exports settings from a RadGrid instance.
/// </summary>
public class GridSettingsPersister
{
    /// <summary>
    /// Initializes an instance of GridSettingsPersister from a RadGrid instance
    /// </summary>
    /// <param name="grid">The RadGrid instance to import and exports settings</param>
    public GridSettingsPersister(RadGrid grid)
        : this(grid, GridSettingsType.All)
    {

    }

    /// <summary>
    /// Initializes an instance of GridSettingsPersister from a RadGrid instance
    /// and a collection GridSettingsType values
    /// </summary>
    /// <param name="grid">The RadGrid instance to import and exports settings</param>
    /// <param name="persistedSettings">
    /// A collection of GridSettingType values specifying the type of grid settings
    /// to import or export
    /// </param>
    public GridSettingsPersister(RadGrid grid, GridSettingsType persistedSettingFlags)
    {
        _grid = grid;
        _persistedSettingTypes = persistedSettingFlags;
        _settings = new GridSettingsCollection();
        _settings.ColumnSettings = new List<ColumnSettings>();
        _settings.AutoGeneratedColumnSettings = new List<ColumnSettings>();
    }

    private RadGrid _grid;
    private GridSettingsType _persistedSettingTypes;
    private GridSettingsCollection _settings;

    /// <summary>
    /// The underlyiong RadGrid instance to import or export settings from
    /// </summary>
    public RadGrid Grid
    {
        get { return _grid; }
    }

    /// <summary>
    /// Gets or sets the GridSettingType flags that specify the grid settings to
    /// export or import
    /// </summary>
    public virtual GridSettingsType PersistedSettingTypes
    {
        get { return _persistedSettingTypes; }
        set { _persistedSettingTypes = value; }
    }

    protected virtual GridSettingsCollection Settings
    {
        get { return _settings; }
        set { _settings = value; }
    }

    /// <summary>
    /// Saves the current grid settings and returns the settings serilized to string
    /// </summary>
    public virtual string SaveSettings()
    {
        return GetSavedSettings().ToString();
    }

    /// <summary>
    /// Saves the current grid settings and retrieves the underlying
    /// GridSettingsCollection instance that contains the grid settings
    /// </summary>
    public virtual GridSettingsCollection GetSavedSettings()
    {
        if (Grid == null)
        {
            throw new NullReferenceException();
        }

        if (IsSettingSpecified(GridSettingsType.Paging)) SavePagingSettings();
        if (IsSettingSpecified(GridSettingsType.Grouping)) SaveGroupByExpressions();
        if (IsSettingSpecified(GridSettingsType.Sorting)) SaveSortExpressions();
        if (IsSettingSpecified(GridSettingsType.Filtering)) SaveFilterExpression();
        if (IsSettingSpecified(GridSettingsType.ColumnSettings)) SaveColumnSettings();

        return Settings;
    }

    protected bool IsSettingSpecified(GridSettingsType settingType)
    {
        return (PersistedSettingTypes & GridSettingsType.All) == GridSettingsType.All ||
               (PersistedSettingTypes & settingType) == settingType;
    }

    protected virtual void SavePagingSettings()
    {
        Settings.PageSize = Grid.MasterTableView.PageSize;
    }

    protected virtual void SaveGroupByExpressions()
    {
        Settings.GroupByExpressionsStates = new object[Grid.MasterTableView.GroupByExpressions.Count];
        for (int i = 0; i < Settings.GroupByExpressionsStates.Length; i++)
        {
            Settings.GroupByExpressionsStates[i] = ((IStateManager)Grid.MasterTableView.GroupByExpressions[i]).SaveViewState();
        }
    }

    protected virtual void SaveSortExpressions()
    {
        Settings.SortExpressionsState = ((IStateManager)Grid.MasterTableView.SortExpressions).SaveViewState();
    }

    protected virtual void SaveFilterExpression()
    {
        Settings.FilterExpression = Grid.MasterTableView.FilterExpression;
    }

    protected virtual void SaveColumnSettings()
    {
        Settings.ColumnSettings.Clear();
        foreach (GridColumn column in Grid.MasterTableView.Columns)
        {
            Settings.ColumnSettings.Add(GetColumnSettings(column));
        }

        Settings.AutoGeneratedColumnSettings.Clear();
        foreach (GridColumn column in Grid.MasterTableView.AutoGeneratedColumns)
        {
            Settings.AutoGeneratedColumnSettings.Add(GetColumnSettings(column));
        }
    }

    private ColumnSettings GetColumnSettings(GridColumn column)
    {
        ColumnSettings colSettings = new ColumnSettings();
        colSettings.UniqueName = column.UniqueName;
        colSettings.Width = column.HeaderStyle.Width;
        colSettings.Visible = column.Visible;
        colSettings.Display = column.Display;
        colSettings.OrderIndex = column.OrderIndex;
        colSettings.CurrentFilterFunction = column.CurrentFilterFunction;
        colSettings.CurrentFilterValue = column.CurrentFilterValue;

        return colSettings;
    }

    private void SetColumnSettings(ref GridColumn column, ColumnSettings setting)
    {
        column.Display = setting.Display;
        column.Visible = setting.Visible;
        column.HeaderStyle.Width = setting.Width;
        column.OrderIndex = setting.OrderIndex;
        column.CurrentFilterFunction = setting.CurrentFilterFunction;
        column.CurrentFilterValue = setting.CurrentFilterValue;
    }

    /// <summary>
    /// Loads grids settings from a serialized string
    /// </summary>
    /// <param name="value">The string that contains the serialized settings</param>
    public virtual void LoadSettings(string value)
    {
        LoadSettings(GridSettingsCollection.LoadFromSerializedData(value));
    }

    /// <summary>
    /// Loads grids settings from a byte array
    /// </summary>
    /// <param name="data">The byte array that contains the serialized grid settings</param>
    public virtual void LoadSettings(byte[] data)
    {
        LoadSettings(GridSettingsCollection.LoadFromSerializedData(data));
    }

    /// <summary>
    /// Loads grid settings from a GridSettingsCollection instance
    /// </summary>
    /// <param name="settings">The GridSettingsCollection instance to load settings from</param>
    public virtual void LoadSettings(GridSettingsCollection settings)
    {
        if (Grid == null || settings == null)
        {
            throw new NullReferenceException();
        }

        Settings = settings;

        if (IsSettingSpecified(GridSettingsType.Paging)) LoadPagingSettings();
        if (IsSettingSpecified(GridSettingsType.Grouping)) LoadGroupByExpressions();
        if (IsSettingSpecified(GridSettingsType.Sorting)) LoadSortExpressions();
        if (IsSettingSpecified(GridSettingsType.Filtering)) LoadFilterExpression();
        if (IsSettingSpecified(GridSettingsType.ColumnSettings)) LoadColumnSettings();
    }

    protected virtual void LoadPagingSettings()
    {
        if (Grid.MasterTableView.AllowPaging && Settings.PageSize > 0)
        {
            Grid.MasterTableView.PageSize = Settings.PageSize;
        }
    }

    protected virtual void LoadGroupByExpressions()
    {
        if (Settings.GroupByExpressionsStates == null) return;

        Grid.MasterTableView.GroupByExpressions.Clear();
        foreach (object expressionState in Settings.GroupByExpressionsStates)
        {
            GridGroupByExpression expression = new GridGroupByExpression();
            ((IStateManager)expression).LoadViewState(expressionState);
            Grid.MasterTableView.GroupByExpressions.Add(expression);
        }
    }

    protected virtual void LoadSortExpressions()
    {
        if (Settings.SortExpressionsState == null) return;

        ((IStateManager)Grid.MasterTableView.SortExpressions).LoadViewState(Settings.SortExpressionsState);
    }

    protected virtual void LoadFilterExpression()
    {
        Grid.MasterTableView.FilterExpression = Settings.FilterExpression;
    }

    protected virtual void LoadColumnSettings()
    {
        foreach (ColumnSettings colSetting in Settings.AutoGeneratedColumnSettings)
        {
            GridColumn column = Grid.MasterTableView.GetColumnSafe(colSetting.UniqueName);

            if (column != null)
            {
                SetColumnSettings(ref column, colSetting);
            }
        }

        foreach (ColumnSettings colSetting in Settings.ColumnSettings)
        {
            GridColumn column = Grid.MasterTableView.GetColumnSafe(colSetting.UniqueName);

            if (column != null)
            {
                SetColumnSettings(ref column, colSetting);
            }
        }
    }

    
}

/// <summary>
/// Enumerates the types of grid settings that can be persisted
/// </summary>
[Flags]
public enum GridSettingsType
{
    Paging = 1,
    Sorting = 2,
    Filtering = 4,
    Grouping = 8,
    ColumnSettings = 16,
    All = 32
}

/// <summary>
/// Represents a collection of grid settings
/// </summary>
[Serializable]
public class GridSettingsCollection
{
    private int _pageSize;
    private object[] _groupByExpressionsStates;
    private object _sortExpressionsState;
    private string _filterExpression;
    private List<ColumnSettings> _columnSettings;
    private List<ColumnSettings> _autoColumnSettings;

    public int PageSize
    {
        get { return _pageSize; }
        set { _pageSize = value; }
    }

    public object[] GroupByExpressionsStates
    {
        get { return _groupByExpressionsStates; }
        set { _groupByExpressionsStates = value; }
    }

    public object SortExpressionsState
    {
        get { return _sortExpressionsState; }
        set { _sortExpressionsState = value; }
    }

    public string FilterExpression
    {
        get { return _filterExpression; }
        set { _filterExpression = value; }
    }

    public List<ColumnSettings> ColumnSettings
    {
        get { return _columnSettings; }
        set { _columnSettings = value; }
    }

    public List<ColumnSettings> AutoGeneratedColumnSettings
    {
        get { return _autoColumnSettings; }
        set { _autoColumnSettings = value; }
    }

    /// <summary>
    /// Returns the serialized object as string
    /// </summary>
    public override string ToString()
    {
        LosFormatter formatter = new LosFormatter();
        using (StringWriter writer = new StringWriter())
        {
            formatter.Serialize(writer, this);
            return writer.ToString();
        }
    }

    /// <summary>
    /// Returns the serialized object as byte array
    /// </summary>
    public byte[] ToArray()
    {
        LosFormatter formatter = new LosFormatter();
        using (MemoryStream stream = new MemoryStream())
        {
            formatter.Serialize(stream, this);
            return stream.ToArray();
        }
    }

    /// <summary>
    /// Gets the GridSettingsCollectionInstance from its serialized string data
    /// </summary>
    /// <param name="data">The object as serialized string data</param>
    public static GridSettingsCollection LoadFromSerializedData(string data)
    {
        LosFormatter formatter = new LosFormatter();
        return (GridSettingsCollection)formatter.Deserialize(data);
    }

    /// <summary>
    /// Gets the GridSettingsCollectionInstance from its serialized byte array
    /// </summary>
    /// <param name="data">The object as serialized byte array</param>
    public static GridSettingsCollection LoadFromSerializedData(byte[] data)
    {
        LosFormatter formatter = new LosFormatter();
        using (MemoryStream stream = new MemoryStream(data))
        {
            return (GridSettingsCollection)formatter.Deserialize(stream);
        }
    }
}

/// <summary>
/// Represents a collection of grid column settings
/// </summary>
[Serializable]
public class ColumnSettings
{
    private string _uniqueName;
    private int _orderIndex;
    private Unit _width;
    private bool _visible;
    private bool _display;
    private GridKnownFunction _currentFilterFunction;
    private string _currentFilterValue;

    public string UniqueName
    {
        get { return _uniqueName; }
        set { _uniqueName = value; }
    }

    public int OrderIndex
    {
        get { return _orderIndex; }
        set { _orderIndex = value; }
    }

    public Unit Width
    {
        get { return _width; }
        set { _width = value; }
    }

    public bool Visible
    {
        get { return _visible; }
        set { _visible = value; }
    }

    public bool Display
    {
        get { return _display; }
        set { _display = value; }
    }

    public GridKnownFunction CurrentFilterFunction
    {
        get { return _currentFilterFunction; }
        set { _currentFilterFunction = value; }
    }

    public string CurrentFilterValue
    {
        get { return _currentFilterValue; }
        set { _currentFilterValue = value; }
    }
}