using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Telerik.Windows.Controls;
using Telerik.Windows.Controls.GridView;
using Telerik.Windows.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System;
using Telerik.Windows.Data;

namespace MathToolBarDemo
{
    public partial class MathToolBar : UserControl
    {
        public MathToolBar()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(MathToolBar_Loaded);

        }
        private GridViewDataColumn dataColumn;

        private string sourceField
        {
            get
            {
                return this.dataColumn.DataMemberBinding.Path.Path;
            }
        }

        void MathToolBar_Loaded(object sender, RoutedEventArgs e)
        {
            this.caption.Text = HeaderText;
            this.dataColumn = this.ParentOfType<GridViewHeaderCell>().Column as GridViewDataColumn;
        }

        public string HeaderText
        {
            get { return (string)GetValue(HeaderTextProperty); }
            set { SetValue(HeaderTextProperty, value); }
        }

        // Using a DependencyProperty as the backing store for HeaderText.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty HeaderTextProperty =
            DependencyProperty.Register("HeaderText", typeof(string), typeof(MathToolBar), new PropertyMetadata(null));

        private void sumButton_Click(object sender, RoutedEventArgs e)
        {
            string functionName = "sum" + sourceField;

            if (this.dataColumn.AggregateFunctions[functionName] == null)
                this.dataColumn.AggregateFunctions.Add(new SumFunction() { FunctionName = functionName, SourceField = sourceField, ResultFormatString = "{0:F}" });

            DisplayResult(functionName);
        }

        private void avgButton_Click(object sender, RoutedEventArgs e)
        {
            string functionName = "avg" + sourceField;

            if (this.dataColumn.AggregateFunctions[functionName] == null)
                this.dataColumn.AggregateFunctions.Add(new AverageFunction() { FunctionName = functionName, SourceField = sourceField, ResultFormatString = "{0:F}" });
            
            DisplayResult(functionName);
        }

        private void DisplayResult(string functionName)
        {
            this.dataColumn.DataControl.CalculateAggregates();
            this.textboxResult.Text = this.dataColumn.DataControl.AggregateResults[functionName].FormattedValue.ToString();
        }

        private void countButton_Click(object sender, RoutedEventArgs e)
        {
            string functionName = "count" + sourceField;

            if (this.dataColumn.AggregateFunctions[functionName] == null)
                this.dataColumn.AggregateFunctions.Add(new CountFunction() { FunctionName = functionName, ResultFormatString = "{0:F}" });

            DisplayResult(functionName);
        }

        private void stddevButton_Click(object sender, RoutedEventArgs e)
        {
            string functionName = "std" + sourceField;

            if (this.dataColumn.AggregateFunctions[functionName] == null)
                this.dataColumn.AggregateFunctions.Add(new StandardDeviationFunction() { FunctionName = functionName, SourceField = sourceField, ResultFormatString ="{0:F}"});

            DisplayResult(functionName);
        }
    }

    public class StandardDeviationFunction : EnumerableSelectorAggregateFunction
    {
        protected override string AggregateMethodName
        {
            get
            {
                return "StdDev";
            }
        }

        protected override Type ExtensionMethodsType
        {
            get
            {
                return typeof(Statistics);
            }
        }
    }

    public static class Statistics
    {
        public static double StdDev<TSource>(IEnumerable<TSource> source, Func<TSource, double> selector)
        {
            int itemCount = source.Count();
            if (itemCount > 1)
            {
                IEnumerable<double> values = from i in source select Convert.ToDouble(selector(i));

                double sum = SumAvg(values);

               return  Math.Sqrt(sum / (itemCount - 1));
            }

            return 0;
        }

        private static double SumAvg(IEnumerable<double> values)
        {
            double average = values.Average();
            double sum = 0;

            foreach (double item in values)
            {
                sum += Math.Pow(item - average, 2);
            }

            return sum;
        }
    }
}
