// THIS FILE IS PART OF SVG PROJECT
// THE SVG PROJECT IS AN OPENSOURCE LIBRARY LICENSED UNDER THE MS-PL License.
// COPYRIGHT (C) svg-net. ALL RIGHTS RESERVED.
// GITHUB: https://github.com/svg-net/SVG

using System;
using System.Collections.Generic;
using System.Globalization;

namespace AntdUI.Svg.Transforms
{
    internal class SvgTransformConverter
    {
        static IEnumerable<string> SplitTransforms(string transforms)
        {
            int transformEnd = 0;

            for (int i = 0; i < transforms.Length; i++)
            {
                if (transforms[i] == ')')
                {
                    yield return transforms.Substring(transformEnd, i - transformEnd + 1).Trim();
                    while (i < transforms.Length && !char.IsLetter(transforms[i])) i++;
                    transformEnd = i;
                }
            }
        }

        public static SvgTransformCollection Parse(string value)
        {
            SvgTransformCollection transformList = new SvgTransformCollection();
            foreach (string transform in SplitTransforms(value))
            {
                if (string.IsNullOrEmpty(transform)) continue;
                var parts = transform.Split('(', ')');
                string transformName = parts[0].Trim(), contents = parts[1].Trim();
                switch (transformName)
                {
                    case "translate":
                        var coords = contents.Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);
                        if (coords.Length == 0 || coords.Length > 2) throw new FormatException("Translate transforms must be in the format 'translate(x [,y])'");
                        if (coords.Length > 1)
                        {
                            string c1 = coords[0].Trim(), c2 = coords[1].Trim();
                            if (c1.EndsWith("%") || c2.EndsWith("%"))
                            {
                                if (c1.EndsWith("%") && c2.EndsWith("%"))
                                {
                                    float x = float.Parse(c1.TrimEnd('%'), NumberStyles.Float, CultureInfo.InvariantCulture), y = float.Parse(c2.TrimEnd('%'), NumberStyles.Float, CultureInfo.InvariantCulture);
                                    transformList.Add(new SvgTranslate(x, true, y, true));
                                }
                                else if (c1.EndsWith("%"))
                                {
                                    float x = float.Parse(c1.TrimEnd('%'), NumberStyles.Float, CultureInfo.InvariantCulture), y = float.Parse(c2, NumberStyles.Float, CultureInfo.InvariantCulture);
                                    transformList.Add(new SvgTranslate(x, true, y, false));
                                }
                                else
                                {
                                    float x = float.Parse(c1, NumberStyles.Float, CultureInfo.InvariantCulture), y = float.Parse(c2.TrimEnd('%'), NumberStyles.Float, CultureInfo.InvariantCulture);
                                    transformList.Add(new SvgTranslate(x, false, y, true));
                                }
                            }
                            else
                            {
                                float x = float.Parse(c1, NumberStyles.Float, CultureInfo.InvariantCulture), y = float.Parse(c2.TrimEnd('%'), NumberStyles.Float, CultureInfo.InvariantCulture);
                                transformList.Add(new SvgTranslate(x, false, y, false));
                            }
                        }
                        else
                        {
                            string c1 = coords[0].Trim();
                            if (c1.EndsWith("%"))
                            {
                                float x = float.Parse(c1.TrimEnd('%'), NumberStyles.Float, CultureInfo.InvariantCulture);
                                transformList.Add(new SvgTranslate(x, true, 0F, false));
                            }
                            else
                            {
                                float x = float.Parse(c1, NumberStyles.Float, CultureInfo.InvariantCulture);
                                transformList.Add(new SvgTranslate(x, false, 0F, false));
                            }
                        }
                        break;
                    case "rotate":
                        var args = contents.Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);
                        if (args.Length != 1 && args.Length != 3) throw new FormatException("Rotate transforms must be in the format 'rotate(angle [cx cy ])'");
                        float angle = float.Parse(args[0], NumberStyles.Float, CultureInfo.InvariantCulture);
                        if (args.Length == 1) transformList.Add(new SvgRotate(angle));
                        else
                        {
                            float cx = float.Parse(args[1], NumberStyles.Float, CultureInfo.InvariantCulture);
                            float cy = float.Parse(args[2], NumberStyles.Float, CultureInfo.InvariantCulture);
                            transformList.Add(new SvgRotate(angle, cx, cy));
                        }
                        break;
                    case "scale":
                        var scales = contents.Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);
                        if (scales.Length == 0 || scales.Length > 2) throw new FormatException("Scale transforms must be in the format 'scale(x [,y])'");
                        float sx = float.Parse(scales[0].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture);
                        if (scales.Length > 1)
                        {
                            float sy = float.Parse(scales[1].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture);
                            transformList.Add(new SvgScale(sx, sy));
                        }
                        else transformList.Add(new SvgScale(sx));
                        break;
                    case "matrix":
                        var points = contents.Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);
                        if (points.Length != 6) throw new FormatException("Matrix transforms must be in the format 'matrix(m11, m12, m21, m22, dx, dy)'");
                        List<float> mPoints = new List<float>();
                        foreach (string point in points) mPoints.Add(float.Parse(point.Trim(), NumberStyles.Float, CultureInfo.InvariantCulture));
                        transformList.Add(new SvgMatrix(mPoints));
                        break;
                    case "shear":
                        var shears = contents.Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);
                        if (shears.Length == 0 || shears.Length > 2) throw new FormatException("Shear transforms must be in the format 'shear(x [,y])'");
                        float hx = float.Parse(shears[0].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture);
                        if (shears.Length > 1)
                        {
                            float hy = float.Parse(shears[1].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture);
                            transformList.Add(new SvgShear(hx, hy));
                        }
                        else transformList.Add(new SvgShear(hx));
                        break;
                    case "skewX":
                        float ax = float.Parse(contents, NumberStyles.Float, CultureInfo.InvariantCulture);
                        transformList.Add(new SvgSkew(ax, 0));
                        break;
                    case "skewY":
                        float ay = float.Parse(contents, NumberStyles.Float, CultureInfo.InvariantCulture);
                        transformList.Add(new SvgSkew(0, ay));
                        break;
                }
            }
            return transformList;
        }
    }
}