using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using System.Threading.Tasks;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

using C1.Xaml.Chart;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238

namespace ChartSamples
{
  /// <summary>
  /// An empty page that can be used on its own or navigated to within a Frame.
  /// </summary>
  public sealed partial class ChartDx : Page
  {
    string[] coef = new string[]
    {
      "AMTMNQQXUYGA",
      "CVQKGHQTPHTE",
      "FIRCDERRPVLD",
      "GIIETPIQRRUL",
      "GLXOESFTTPSV",
      "GXQSNSKEECTX",
      "HGUHDPHNSGOH",
      "ILIBVPKJWGRR"
    };
    Brush[] brushes = new Brush[] 
    {
      new SolidColorBrush(Colors.Green),
      new SolidColorBrush(Colors.Blue),
      new SolidColorBrush(Colors.Red),
      new SolidColorBrush(Colors.LightGray),
      new SolidColorBrush(Colors.White),
    };
    Random rnd = new Random();
    int cnt = 5000;
    double[] x;
    double[] y;

    public ChartDx()
    {
      this.InitializeComponent();
      CreateData();
      CreateChart();
    }

    /// <summary>
    /// Invoked when this page is about to be displayed in a Frame.
    /// </summary>
    /// <param name="e">Event data that describes how this page was reached.  The Parameter
    /// property is typically used to configure the page.</param>
    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
    }

    void CreateChart()
    {
      chart.BeginUpdate();
      chart.Data.Children.Clear();
      chart.Data.Children.Add(
        new XYDataSeries()
        {
          XValuesSource = x,
          ValuesSource = y,
          SymbolSize = new Size(3, 3),
          SymbolMarker = Marker.Box,
          RenderMode = RenderMode.Direct2D,
          SymbolFill = brushes[rnd.Next(brushes.Length)],
          SymbolStroke = null
        });
      chart.ChartType = ChartType.XYPlot;
      chart.EndUpdate();
    }

    void CreateData()
    {
      x = new double[cnt];
      y = new double[cnt];

      double[] c = StringToCoeff(coef[rnd.Next(coef.Length)]);

      for (int i = 1; i < cnt; i++)
      {
        Point pt = Iterate(x[i - 1], y[i - 1], c);
        x[i] = pt.X; y[i] = pt.Y;
      }
    }

    Point 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 Point(x1, y1);
    }

    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;
    }

    async void btnNew_Click(object sender, RoutedEventArgs e)
    {
      pnl.IsEnabled = false;
      tbCalc.Visibility = Visibility.Visible;
      chart.Opacity = 0.2;

      Task t = new Task
      (
          () =>
          {
            CreateData();
          }
      );
      t.Start();

      await t;
      CreateChart();

      tbCalc.Visibility = Visibility.Collapsed;
      pnl.IsEnabled = true;
      chart.Opacity = 1;
    }

    private void RadioButton_Checked(object sender, RoutedEventArgs e)
    {
      if (pnl == null)
        return;
      var rb = (RadioButton)sender;
      int count = int.Parse((string)rb.Content);
      if (count != cnt)
      {
        cnt = count;
        btnNew_Click(btnNew, new RoutedEventArgs());
      }
    }
  }
}
