using C1.Chart;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FlexChartExplorer
{
    class DataCreator
    {
        public delegate double MathActionDouble(double num);
        public delegate double MathActionInt(int num);

        public static Dictionary<ChartType, string> CreateSimpleChartTypes()
        {
            Dictionary<ChartType, string> types = new Dictionary<ChartType, string>();
            types = new Dictionary<ChartType, string>();
            types.Add(ChartType.Column, Strings.Column);
            types.Add(ChartType.Bar, Strings.Bar);
            types.Add(ChartType.Line, Strings.Line);
            types.Add(ChartType.Scatter, Strings.Scatter);
            types.Add(ChartType.LineSymbols, Strings.LineSymbols);
            types.Add(ChartType.Area, Strings.Area);
            types.Add(ChartType.Spline, Strings.Spline);
            types.Add(ChartType.SplineArea, Strings.SplineArea);
            types.Add(ChartType.SplineSymbols, Strings.SplineSymbols);

            return types;
        }

        public static Dictionary<ChartType, string> CreateFinancialChartTypes()
        {
            Dictionary<ChartType, string> types = new Dictionary<ChartType, string>();
            types.Add(ChartType.Candlestick, Strings.Candlestick);
            types.Add(ChartType.HighLowOpenClose, Strings.HighLowOpenClose);

            return types;
        }

        public static List<DataPoint> Create(MathActionDouble function, double from, double to, double step)
        {
            var result = new List<DataPoint>();
            var count = (to - from) / step;

            for (double r = from; r < to; r += step)
            {
                result.Add(new DataPoint()
                {
                    XVals = r,
                    YVals = function(r)
                });
            }
            return result;
        }

        public static List<DataPoint> Create(MathActionInt function, int from, int to, int step)
        {
            var result = new List<DataPoint>();
            var count = (to - from) / step;

            for (int r = from; r < to; r += step)
            {
                result.Add(new DataPoint()
                {
                    XVals = r,
                    YVals = function(r)
                });
            }
            return result;
        }

        public static List<DataPoint> Create(MathActionDouble functionX, MathActionDouble functionY, int ptsCount)
        {
            var result = new List<DataPoint>();

            for (double i = 0; i < ptsCount; i++)
            {
                result.Add(new DataPoint()
                {
                    XVals = functionX(i),
                    YVals = functionY(i)
                });
            }
            return result;
        }

        public static List<DataPoint> Create(string[] coef, int ptsCount)
        {
            var result = new List<DataPoint>();

            double[] x = new double[ptsCount];
            double[] y = new double[ptsCount];
            Random rnd = new Random();
            double[] c = StringToCoeff(coef[rnd.Next(coef.Length)]);

            for (int i = 1; i < ptsCount; i++)
            {
                DataPoint pt = Iterate(x[i - 1], y[i - 1], c);
                result.Add(pt);
                x[i] = pt.XVals; y[i] = pt.YVals;
            }

            return result;
        }

        public static List<FruitDataItem> CreateFruit()
        {
            var fruits = new string[] { "Oranges", "Apples", "Pears", "Bananas" };
            var count = fruits.Length;
            var result = new List<FruitDataItem>();
            var rnd = new Random();
            for (var i = 0; i < count; i++)
                result.Add(new FruitDataItem()
                {
                    Fruit = fruits[i],
                    March = rnd.Next(20),
                    April = rnd.Next(20),
                    May = rnd.Next(20),
                });
            return result;
        }

        public static double Sinus(double x)
        {
            return Math.Sin(x);
        }

        public static double Test1(double x)
        {
            return (Math.Pow(-x, 2 / 3) + Math.Sqrt(Math.Pow(x, 4 / 3) - 4 * Math.Pow(x, 2) + 4)) / 2;
        }

         static DataPoint Iterate(double x, double y, double[] c)
        {
            double x1 = c[0] + c[1] * x + c[2] * x * x + c[3] * x * y + c[4] * y + c[5] * y * y;
            double y1 = c[6] + c[7] * x + c[8] * x * x + c[9] * x * y + c[10] * y + c[11] * y * y;

            return new DataPoint() { XVals = x1, YVals = y1 };
        }

        static double[] StringToCoeff(string s)
        {
            int len = s.Length;
            double[] c = new double[len];

            for (int i = 0; i < len; i++)
            {
                c[i] = -1.2 + 0.1 * (s[i] - 'A');
            }

            return c;
        }
    }

    public class FruitDataItem
    {
        public string Fruit { get; set; }
        public double March { get; set; }
        public double April { get; set; }
        public double May { get; set; }
    }

    public class DataPoint
    {
        public double XVals { get; set; }
        public double YVals { get; set; }
    }
}
