using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Globalization;
using C1.Silverlight.FlexGrid;

namespace C1.Silverlight.FlexGridExcel
{
    /// <summary>
    /// Special type of group row used to show FlatList items.
    /// </summary>
    /// <remarks>
    /// This is similar to a regular <see cref="GroupRow"/> because it groups child rows and can be 
    /// collapsed or expanded, but unlike regular group rows, these are bound to data items. Also,
    /// they automatically calculate aggregates for data items that have children and their aggregate 
    /// properties are set to null.
    /// </remarks>
    public class FlatListRow : GroupRow
    {
        /// <summary>
        /// Initializes a new instance of a <see cref="FlatListRow"/>.
        /// </summary>
        public FlatListRow()
        {
            IsReadOnly = false;
        }
        /// <summary>
        /// Initializes a new instance of a <see cref="FlatListRow"/>.
        /// </summary>
        /// <param name="dataItem">Object bound to this row.</param>
        /// <param name="level">Grouping level for this row.</param>
        public FlatListRow(object dataItem, int level)
            : this()
        {
            DataItem = dataItem;
            Level = level;
        }
        /// <summary>
        /// Overridden to calculate aggregates for items that contain null values.
        /// </summary>
        /// <param name="col"><see cref="Column"/> that contains the value that should be retrieved.</param>
        /// <returns>The data contained in a specified column of this row.</returns>
        protected override object GetData(Column col)
        {
            // get value as usual
            var value = base.GetData(col);

            // special handling for empty strings
            if (object.Equals(value, string.Empty))
            {
                value = null;
            }

            // if the value is null and we need an aggregate, get it now
            if (value == null &&
                DataItem != null &&
                col.PropertyInfo != null &&
                col.GroupAggregate != Aggregate.None && // we need an aggregate
                !Grid.IncludeInAggregate(this, col))    // and have no actual data
            {
                // get value
                var rng = GetCellRange();
                rng.Column = rng.Column2 = col.Index;
                var aggValue = Grid.GetAggregate(col.GroupAggregate, rng);
                try
                {
                    var type = col.DataType;
                    if (type != null && type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
                    {
                        type = type.GetGenericArguments()[0];
                    }
                    value = Convert.ChangeType(aggValue, type, CultureInfo.CurrentUICulture);

                    // store aggregate value in model using PropertyInfo
                    //col.PropertyInfo.SetValue(DataItem, value, null);

                    // store aggregate value in model using binding
                    if (value != null && aggValue != 0 && col.Binding != null)
                    {
                        if (_tb == null)
                        {
                            _tb = new TextBlock();
                        }
                        _tb.DataContext = DataItem;
                        _tb.SetBinding(TextBlock.TagProperty, col.Binding);
                        _tb.Tag = value;
                    }
                }
                catch
                {
                    // conversion failed...
                }
            }

            // return the value we got
            return value;
        }
        static TextBlock _tb;
    }
}
