using System;
using System.Collections.Generic;
using System.ComponentModel;
using Xamarin.Forms;
using TheGameExtreme.model.@event;
using TheGameExtreme.viewmodel;
using SkiaSharp;
using System.IO;
using System.Reflection;
using SkiaSharp.Views.Forms;
using TouchTracking;
using Xamarin.Essentials;
using TheGameExtreme.model.card;

namespace TheGameExtreme.view
{

    // Learn more about making custom code visible in the Xamarin.Forms previewer
    // by visiting https://aka.ms/xamarinforms-previewer
    [DesignTimeVisible(false)]
    public partial class MainPage : ContentPage
    {
        private Main viewmodel;
        Button button;
        List<string> playersNames;
        List<TouchManipulationBitmap> textCollection = new List<TouchManipulationBitmap>();
        List<TouchManipulationBitmap> stackCollection = new List<TouchManipulationBitmap>();
        Dictionary<long, TouchManipulationBitmap> textDictionary = new Dictionary<long, TouchManipulationBitmap>();
        private SKCanvas canvas;


        public MainPage(List<string> playersNames)
        {
            this.playersNames = playersNames;

            InitializeComponent();
            NavigationPage.SetHasNavigationBar(this, false);

            EndTurnButton.Text = AppRessource.StrEndTurn;   // Trouver le moyen d'avoir du binding

            viewmodel = new Main(playersNames);

            viewmodel.EndGame += OnEndGame;

            viewmodel.AlertChanged += OnAlertChanged;

            pseudo.SetBinding(Label.TextProperty, new Binding("Pseudo", source: viewmodel));

            InflateStack();
            InflateHand();
        }


        private void OnAlertChanged(object sender, EventArgs args)
        {
            if (viewmodel.Alert != null)
            {
                DisplayAlert("", viewmodel.Alert, "OK");
                viewmodel.Alert = null;
            }
        }



        public void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
        {
            canvas = args.Surface.Canvas;
            canvas.Clear();

            for (int i = 0; i < stackCollection.Count; i++)
            {
                if (i < (stackCollection.Count * 0.5))
                {
                    stackCollection[i].Paint(canvas, SKColors.Green);
                }
                else
                {
                    stackCollection[i].Paint(canvas, SKColors.Red);
                }
            }

            foreach (TouchManipulationBitmap textPaint in textCollection)
            {
                textPaint.Paint(canvas, SKColors.SkyBlue);
            }
        }

        public void OnTouchEffectAction(object sender, TouchActionEventArgs args)
        {
            TouchTrackingPoint pt = args.Location;
            SKPoint point =
                new SKPoint((float)(canvasView.CanvasSize.Width * pt.X / canvasView.Width),
                            (float)(canvasView.CanvasSize.Height * pt.Y / canvasView.Height));

            switch (args.Type)
            {
                case TouchActionType.Pressed:
                    for (int i = textCollection.Count - 1; i >= 0; i--)
                    {
                        TouchManipulationBitmap textPaint = textCollection[i];

                        if (textPaint.HitTest(point))
                        {
                            // Move bitmap to end of collection
                            textCollection.Remove(textPaint);
                            textCollection.Add(textPaint);

                            // Do the touch processing
                            textDictionary.Add(args.Id, textPaint);
                            textPaint.ProcessTouchEvent(args.Id, args.Type, point);
                            canvasView.InvalidateSurface();
                            break;
                        }
                    }
                    break;

                case TouchActionType.Moved:
                    if (textDictionary.ContainsKey(args.Id))
                    {
                        TouchManipulationBitmap bitmap = textDictionary[args.Id];
                        bitmap.ProcessTouchEvent(args.Id, args.Type, point);
                        canvasView.InvalidateSurface();
                    }
                    break;

                case TouchActionType.Released:


                case TouchActionType.Cancelled:
                    if (textDictionary.ContainsKey(args.Id))
                    {
                        TouchManipulationBitmap bitmap = textDictionary[args.Id];
                        bool find = false;
                        foreach (TouchManipulationBitmap stack in stackCollection)
                        {
                            if (stack.HitTest(point))
                            {
                                int indexPile = stackCollection.IndexOf(stack);
                                if (played(indexPile, decimal.Parse(bitmap.Value)))
                                {
                                    point = stack.InitialPoint;
                                    bitmap.ProcessTouchEvent(args.Id, TouchActionType.Moved, point);
                                    canvasView.InvalidateSurface();
                                    bitmap.InitialPoint = stackCollection[stackCollection.IndexOf(stack)].InitialPoint;
                                    stackCollection[stackCollection.IndexOf(stack)] = bitmap;
                                    textCollection.RemoveAt(textCollection.Count - 1);
                                    find = true;
                                }
                                break;
                            }
                        }
                        if (!find)
                        {
                            point = bitmap.InitialPoint;
                            bitmap.ProcessTouchEvent(args.Id, TouchActionType.Moved, point);
                            canvasView.InvalidateSurface();
                        }
                        bitmap.ProcessTouchEvent(args.Id, args.Type, point);
                        textDictionary.Remove(args.Id);
                        canvasView.InvalidateSurface();
                    }
                    break;
            }
        }

        //public void OnTouchModePickerSelectedIndexChanged(object sender, EventArgs args)
        //{
        //    if (textPaint != null)
        //    {
        //        Picker picker = (Picker)sender;
        //        textPaint.TouchManager.Mode = (TouchManipulationMode)picker.SelectedItem;
                
        //    }
        //}

        private void InflateStack()
        {
            stackCollection.Clear();

            SKPaint textPaint = new SKPaint();
            float textWidth = textPaint.MeasureText("001");
            float textSize = 0.05f * (float)DeviceDisplay.MainDisplayInfo.Width * textPaint.TextSize / textWidth;
            SKPoint position = new SKPoint((float)((DeviceDisplay.MainDisplayInfo.Width * 0.05) - (textWidth * 0.5)), (float)((DeviceDisplay.MainDisplayInfo.Height * 0.1) + (DeviceDisplay.MainDisplayInfo.Height * 0.9) * 0.01 + 2 * textSize));

            for (int i = 0; i < viewmodel.getListOrderedStacks().Count; i++)
            {
                textPaint = new SKPaint();
                textPaint.TextSize = textSize;

                stackCollection.Add(new TouchManipulationBitmap(textPaint, viewmodel.getListOrderedStacks()[i].Peek().Value)
                {
                    Matrix = SKMatrix.MakeTranslation(position.X, position.Y),
                    InitialPoint = position
                });

                position.X += (float)((DeviceDisplay.MainDisplayInfo.Width * 0.9) / viewmodel.getListOrderedStacks().Count);
            }
        }

        private void InflateHand()
        {
            SKPaint textPaint = new SKPaint();
            float textWidth = textPaint.MeasureText("001");
            float textSize = 0.05f * (float)DeviceDisplay.MainDisplayInfo.Width * textPaint.TextSize / textWidth;
            SKPoint position = new SKPoint((float)(DeviceDisplay.MainDisplayInfo.Width * 0.05), (float)((DeviceDisplay.MainDisplayInfo.Height * 0.9) - (DeviceDisplay.MainDisplayInfo.Height * 0.9) * 0.2 - textSize));

            for (int i = 0; i < viewmodel.CurrentHand.Count; i++)
            {
                textPaint = new SKPaint();
                textPaint.TextSize = textSize;
                position.X -= (float)(textWidth * 0.5);

                textCollection.Add(new TouchManipulationBitmap(textPaint, viewmodel.CurrentHand[i].Value)
                {
                    Matrix = SKMatrix.MakeTranslation(position.X, position.Y),
                    InitialPoint = position
                });

                position.X += (float)((DeviceDisplay.MainDisplayInfo.Width * 0.9) / viewmodel.CurrentHand.Count);
            }
        }

        private void OnEndGame(object sender, EventArgs args)
        {
            button = (Button)gameOption.Children[0];
            gameOption.Children.Clear();
            Button retryButton = new Button();
            retryButton.Text = "Retry";
            retryButton.Clicked += retry;
            retryButton.BackgroundColor = (Color)Application.Current.Resources["SkyBlueColor"];
            gameOption.Children.Add(retryButton);
        }

        private bool played(int numStack, decimal value)
        {
            if (!viewmodel.played(numStack, value))
            {
                return false;
            }
            return true;
        }

        private void retry(object sender, EventArgs args)
        {
            viewmodel = new Main(playersNames);

            viewmodel.EndGame += OnEndGame;

            pseudo.SetBinding(Label.TextProperty, new Binding("Pseudo", source: viewmodel));

            textCollection.Clear();
            textDictionary.Clear();
            canvasView.InvalidateSurface();
            InflateStack();
            InflateHand();

            gameOption.Children.Clear();
            gameOption.Children.Add(button);
        }

        private void EndTurn(object sender, EventArgs args)
        {
            if (!viewmodel.endTurn())
            {
                textCollection.Clear();
                textDictionary.Clear();
                stackCollection.Clear();
                canvasView.InvalidateSurface();
                InflateStack();
                InflateHand();
            }
        }

        private async void PlayToHome(object sender, EventArgs args)
        {
            await Navigation.PopToRootAsync();
        }
    }
}
