using SvgPathProperties;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

namespace PCUT.Extensions.Converters
{
    internal abstract class PathConverter
    {
        private PathConverter _next;

        private void SetNext(PathConverter next)
        {
            _next = next;
        }

        public SvgPath GetSvgPath(XElement element)
        {
            if (CanApply(element))
            {
                return GetPathFromElement(element);
            }
            else if (_next != null)
            {
                return _next.GetSvgPath(element);
            }
            else
            {
                return null;
            }
        }

        protected abstract bool CanApply(XElement element);
        protected abstract SvgPath GetPathFromElement(XElement element);

        public void CopyAttribute(XElement source, XElement target)
        {
            foreach (var attribute in source.Attributes().Where(x => !ExcludedAttributes.Contains(x.Name.LocalName)))
            {
                target.SetAttributeValue(attribute.Name, attribute.Value);
            }
        }
        protected abstract IEnumerable<string> ExcludedAttributes { get; }

        public static PathConverterBuilder Builder() => new PathConverterBuilder();
        public class PathConverterBuilder
        {
            private readonly Stack<PathConverter> _pathConverters = new Stack<PathConverter>();

            public PathConverterBuilder AddPath()
            {
                _pathConverters.Push(new PathElementConverter());
                return this;
            }

            public PathConverterBuilder AddRect()
            {
                _pathConverters.Push(new RectElementConverter());
                return this;
            }

            public PathConverterBuilder AddPolygon()
            {
                _pathConverters.Push(new PolygonElementConverter());
                return this;
            }

            public PathConverterBuilder AddCircle()
            {
                _pathConverters.Push(new CircleElementConverter());
                return this;
            }

            public PathConverterBuilder AddEllipse()
            {
                _pathConverters.Push(new EllipseElementConverter());
                return this;
            }

            public PathConverter Build()
            {
                PathConverter current = null;
                while (_pathConverters.Count > 0)
                {
                    var converter = _pathConverters.Pop();
                    converter.SetNext(current);
                    current = converter;
                }
                return current;
            }
        }
    }
}
