using SkiaSharp;
using SkiaSharp.Views.Forms;
using System;

using Xamarin.Forms;

namespace Billing.UI
{
    public class ColorPicker : SKCanvasView
    {
        public static readonly BindableProperty ColorProperty = Helper.Create<Color, ColorPicker>(nameof(Color));
        public static readonly BindableProperty CommandProperty = Helper.Create<Command, ColorPicker>(nameof(Command));

        public Color Color
        {
            get => (Color)GetValue(ColorProperty);
            set => SetValue(ColorProperty, value);
        }
        public Command Command
        {
            get => (Command)GetValue(CommandProperty);
            set => SetValue(CommandProperty, value);
        }

        private SKPoint? lastTouch;

        public ColorPicker()
        {
            EnableTouchEvents = true;
        }

        protected override void OnPaintSurface(SKPaintSurfaceEventArgs e)
        {
            base.OnPaintSurface(e);
            var skInfo = e.Info;
            var skSurface = e.Surface;
            var skCanvas = skSurface.Canvas;

            var width = skInfo.Width;
            var height = skInfo.Height;

            skCanvas.Clear(SKColors.White);

            using (var paint = new SKPaint())
            {
                paint.IsAntialias = true;
                var colors = new SKColor[]
                {
                new SKColor(255, 0, 0),   // Red
                new SKColor(255, 255, 0), // Yellow
                new SKColor(0, 255, 0),   // Green (Lime)
                new SKColor(0, 255, 255), // Aqua
                new SKColor(0, 0, 255),   // Blue
                new SKColor(255, 0, 255), // Fuchsia
                new SKColor(255, 0, 0),   // Red
                };

                using var shader = SKShader.CreateLinearGradient(
                    new SKPoint(0, 0),
                    new SKPoint(width, 0),
                    colors,
                    null,
                    SKShaderTileMode.Clamp);
                paint.Shader = shader;
                skCanvas.DrawPaint(paint);
            }

            using (var paint = new SKPaint())
            {
                paint.IsAntialias = true;
                var colors = new SKColor[]
                {
                    SKColors.Transparent,
                    SKColors.Black
                };
                using var shader = SKShader.CreateLinearGradient(
                    new SKPoint(0, 0),
                    new SKPoint(0, height),
                    colors,
                    null,
                    SKShaderTileMode.Clamp);
                paint.Shader = shader;
                skCanvas.DrawPaint(paint);
            }

            if (lastTouch != null)
            {
                var touch = lastTouch.Value;
                SKColor touchColor;
                using (SKBitmap bitmap = new(skInfo))
                {
                    IntPtr dstPixels = bitmap.GetPixels();
                    skSurface.ReadPixels(
                        skInfo,
                        dstPixels,
                        skInfo.RowBytes,
                        (int)touch.X, (int)touch.Y);
                    touchColor = bitmap.GetPixel(0, 0);
                }

                using (SKPaint paintTouch = new())
                {
                    paintTouch.Style = SKPaintStyle.Fill;
                    paintTouch.Color = SKColors.White;
                    paintTouch.IsAntialias = true;

                    skCanvas.DrawCircle(
                        touch.X,
                        touch.Y,
                        18,
                        paintTouch);

                    paintTouch.Color = touchColor;
                    skCanvas.DrawCircle(
                        touch.X,
                        touch.Y,
                        12,
                        paintTouch);
                }

                var color = touchColor.ToFormsColor();
                Color = color;
                Command?.Execute(color);
            }
        }

        protected override void OnTouch(SKTouchEventArgs e)
        {
            base.OnTouch(e);
            lastTouch = e.Location;

            var size = CanvasSize;
            if (e.Location.X > 0 && e.Location.X < size.Width &&
                e.Location.Y > 0 && e.Location.Y < size.Height)
            {
                e.Handled = true;
                InvalidateSurface();
            }
        }
    }
}