using System;
using System.Collections.Generic;
using Windows.Foundation;
using Windows.System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Shapes;

namespace Whirligig
{
    public sealed partial class MainPage : Page
    {
        const double Radius = 24;           // 6 mm
        const double AngleIncrement = 0.5;  // radiany na piksel

        class TouchInfo
        {
            public Point LastPoint;
            public Polyline Polyline;
            public double Angle;
        }

        Dictionary<uint, TouchInfo> pointerDictionary = new Dictionary<uint, TouchInfo>();

        public MainPage()
        {
            this.InitializeComponent();
        }

        protected override void OnPointerPressed(PointerRoutedEventArgs args)
        {
            // Odczytanie danych z argumentu zdarzenia
            uint id = args.Pointer.PointerId;
            Point point = args.GetCurrentPoint(this).Position;

            // Tworzenie Polyline
            Polyline polyline = new Polyline
            {
                Stroke = this.Resources["ApplicationForegroundThemeBrush"] as Brush,
                StrokeThickness = 1,
            };

            // Dodanie do Grid
            contentGrid.Children.Add(polyline);

            // Tworzenie TouchInfo
            TouchInfo touchInfo = new TouchInfo
            {
                LastPoint = point,
                Polyline = polyline
            };

            // Dodanie do słownika
            pointerDictionary.Add(id, touchInfo);

            // Przechwycenie wskaźnika
            CapturePointer(args.Pointer);
            base.OnPointerPressed(args);
        }

        protected override void OnPointerMoved(PointerRoutedEventArgs args)
        {
            // Odczytanie danych z argumentu zdarzenia
            uint id = args.Pointer.PointerId;
            Point point = args.GetCurrentPoint(this).Position;

            // Jeżeli nie ma ID w słowniku, nic nie rób
            if (!pointerDictionary.ContainsKey(id))
                return;

            // Pobranie obiektów TouchInfo
            Polyline polyline = pointerDictionary[id].Polyline;
            Point lastPoint = pointerDictionary[id].LastPoint;
            double angle = pointerDictionary[id].Angle;

            // Odległość od punktu bieżącego do poprzedniego
            double distance = Math.Sqrt(Math.Pow(point.X - lastPoint.X, 2) +
                                        Math.Pow(point.Y - lastPoint.Y, 2));

            int divisions = (int)distance;

            for (int i = 0; i < divisions; i++)
            {
                // Podział odległości pomiędzy ostatnim punktem a nowym
                double x = (i * point.X + (divisions - i) * lastPoint.X) / divisions;
                double y = (i * point.Y + (divisions - i) * lastPoint.Y) / divisions;
                Point pt = new Point(x, y);

                // Zwiększenie kąta
                angle += distance * AngleIncrement / divisions;

                // Obrót punktu
                pt.X += Radius * Math.Cos(angle);
                pt.Y += Radius * Math.Sin(angle);

                // Dodawanie do Polyline
                polyline.Points.Add(pt);
            }

            // Zapisanie nowych danych
            pointerDictionary[id].LastPoint = point;
            pointerDictionary[id].Angle = angle;

            base.OnPointerMoved(args);
        }

        protected override void OnPointerReleased(PointerRoutedEventArgs args)
        {
            // Odczytanie danych z argumentu zdarzenia
            uint id = args.Pointer.PointerId;

            // Jeżeli ID jest w słowniku, usuń go
            if (pointerDictionary.ContainsKey(id))
                pointerDictionary.Remove(id);

            base.OnPointerReleased(args);
        }

        protected override void OnPointerCaptureLost(PointerRoutedEventArgs args)
        {
            // Odczytanie danych z argumentu zdarzenia
            uint id = args.Pointer.PointerId;

            // Jeżeli ID jest w słowniku, porzuć operację rysowania
            if (pointerDictionary.ContainsKey(id))
            {
                contentGrid.Children.Remove(pointerDictionary[id].Polyline);
                pointerDictionary.Remove(id);
            }

            base.OnPointerCaptureLost(args);
        }
    }
}
