using PCUT.Extensions.Transforms;
using SvgPathProperties;
using SvgPathProperties.Base;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PCUT.Extensions
{
    public static class SvgTransformExtensions
    {
        public static SvgPath Apply(this SvgTransform transform, SvgPath path)
        {
            if (transform == null || path == null)
                return path;

            var transformedPath = new SvgPath();
            foreach (var segment in path.Segments)
            {
                switch (segment)
                {
                    case MoveCommand moveSegment:
                        var moveCommand = transform.Apply(moveSegment);
                        transformedPath.AddMoveTo(moveCommand.X, moveCommand.Y);
                        break;
                    case LineCommand lineSegment:
                        if (lineSegment.ClosePath)
                        {
                            transformedPath.AddClosePath();
                        }
                        else
                        {
                            var lineCommand = transform.Apply(lineSegment);
                            transformedPath.AddLineTo(lineCommand.ToX, lineCommand.ToY);
                        }
                        break;
                    case BezierCommand bezierSegment:
                        var bezierCommand = transform.Apply(bezierSegment);
                        if (!bezierCommand.IsQuadratic)
                            transformedPath.AddCubicBezierCurve(bezierCommand.Cp1.X, bezierCommand.Cp1.Y, bezierCommand.Cp2OrEnd.X, bezierCommand.Cp2OrEnd.Y, bezierCommand.End.X, bezierCommand.End.Y);
                        else
                            transformedPath.AddQuadraticBezierCurve(bezierCommand.Cp1.X, bezierCommand.Cp1.Y, bezierCommand.Cp2OrEnd.X, bezierCommand.Cp2OrEnd.Y);
                        break;
                    case ArcCommand arcSegment:
                        var arcCommand = transform.Apply(arcSegment);
                        transformedPath.AddArc(arcCommand.Rx, arcCommand.Ry, arcCommand.XAxisRotate, arcCommand.LargeArcFlag, arcCommand.SweepFlag, arcCommand.ToX, arcCommand.ToY);
                        break;
                }
            }
            return transformedPath;
        }

        private static MoveCommand Apply(this SvgTransform transform, MoveCommand command)
        {
            var (x, y) = transform.Transform(command.X, command.Y);
            return new MoveCommand(x, y);
        }

        private static LineCommand Apply(this SvgTransform transform, LineCommand command)
        {
            var (fromX, fromY) = transform.Transform(command.FromX, command.FromY);
            var (toX, toY) = transform.Transform(command.ToX, command.ToY);
            return new LineCommand(fromX, toX, fromY, toY, command.ClosePath);
        }

        private static BezierCommand Apply(this SvgTransform transform, BezierCommand command)
        {
            var from = transform.Apply(command.From);
            var cp1 = transform.Apply(command.Cp1);
            var cp2 = transform.Apply(command.Cp2OrEnd);
            (double? X, double? Y) end = command.IsQuadratic ? default : transform.Transform(command.End.X, command.End.Y);
            return new BezierCommand(from.X, from.Y, cp1.X, cp1.Y, cp2.X, cp2.Y, end.X, end.Y);
        }

        private static ArcCommand Apply(this SvgTransform transform, ArcCommand command)
        {
            throw new NotImplementedException();
        }

        private static Point Apply(this SvgTransform transform, Point point)
        {
            var (x, y) = transform.Transform(point.X, point.Y);
            return new Point(x, y);
        }
    }
}
