<commit_before>﻿using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Core2D.Editor.Input;
using Core2D.Editor.Tools.Path;
using Core2D.Editor.Tools.Settings;
using Core2D.Interfaces;
using Core2D.Path;
using Core2D.Path.Segments;
using Core2D.Shapes;
using Core2D.Style;

namespace Core2D.Editor.Tools
{
    /// <summary>
    /// Path tool.
    /// </summary>
    public class ToolPath : ObservableObject, IEditorTool
    {
        private readonly IServiceProvider _serviceProvider;
        private ToolSettingsPath _settings;
        private readonly PathToolLine _pathToolLine;
        private readonly PathToolArc _pathToolArc;
        private readonly PathToolCubicBezier _pathToolCubicBezier;
        private readonly PathToolQuadraticBezier _pathToolQuadraticBezier;
        private readonly PathToolMove _pathToolMove;

        /// <summary>
        /// Gets or sets flag indicating whether path was initialized.
        /// </summary>
        internal bool IsInitialized { get; set; }

        /// <summary>
        /// Gets or sets current path.
        /// </summary>
        internal IPathShape Path { get; set; }

        /// <summary>
        /// Gets or sets current geometry.
        /// </summary>
        internal IPathGeometry Geometry { get; set; }

        /// <summary>
        /// Gets or sets current geometry context.
        /// </summary>
        internal IGeometryContext GeometryContext { get; set; }

        /// <summary>
        /// Gets or sets previous path tool.
        /// </summary>
        internal IPathTool PreviousPathTool { get; set; }

        /// <inheritdoc/>
        public string Title => "Path";

        /// <summary>
        /// Gets or sets the tool settings.
        /// </summary>
        public ToolSettingsPath Settings
        {
            get => _settings;
            set => Update(ref _settings, value);
        }

        /// <summary>
        /// Initialize new instance of <see cref="ToolPath"/> class.
        /// </summary>
        /// <param name="serviceProvider">The service provider.</param>
        public ToolPath(IServiceProvider serviceProvider) : base()
        {
            _serviceProvider = serviceProvider;
            _settings = new ToolSettingsPath();
            _pathToolLine = serviceProvider.GetService<PathToolLine>();
            _pathToolArc = serviceProvider.GetService<PathToolArc>();
            _pathToolCubicBezier = serviceProvider.GetService<PathToolCubicBezier>();
            _pathToolQuadraticBezier = serviceProvider.GetService<PathToolQuadraticBezier>();
            _pathToolMove = serviceProvider.GetService<PathToolMove>();
            IsInitialized = false;
        }

        /// <inheritdoc/>
        public override object Copy(IDictionary<object, object> shared)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Remove last <see cref="PathSegment"/> segment from the previous figure.
        /// </summary>
        /// <typeparam name="T">The type of the path segment to remove.</typeparam>
        public void RemoveLastSegment<T>() where T : PathSegment
        {
            var figure = Geometry?.Figures.LastOrDefault();
            if (figure != null)
            {
                if (figure.Segments.LastOrDefault() is T segment)
                {
                    figure.Segments = figure.Segments.Remove(segment);
                }
            }
        }

        /// <summary>
        /// Remove last segment from the previous figure.
        /// </summary>
        public void RemoveLastSegment()
        {
            if (PreviousPathTool == _pathToolLine)
            {
                RemoveLastSegment<LineSegment>();
                _pathToolLine.Reset();
            }
            else if (PreviousPathTool == _pathToolArc)
            {
                RemoveLastSegment<ArcSegment>();
                _pathToolArc.Reset();
            }
            else if (PreviousPathTool == _pathToolCubicBezier)
            {
                RemoveLastSegment<CubicBezierSegment>();
                _pathToolCubicBezier.Reset();
            }
            else if (PreviousPathTool == _pathToolQuadraticBezier)
            {
                RemoveLastSegment<QuadraticBezierSegment>();
                _pathToolQuadraticBezier.Reset();
            }

            var editor = _serviceProvider.GetService<IProjectEditor>();
            editor.Project.CurrentContainer.WorkingLayer.Invalidate();
            editor.Project.CurrentContainer.HelperLayer.Invalidate();
        }

        /// <summary>
        /// Gets last point in the current path.
        /// </summary>
        /// <returns>The last path point.</returns>
        public IPointShape GetLastPathPoint()
        {
            var figure = Geometry.Figures.LastOrDefault();
            if (figure != null)
            {
                switch (figure.Segments.LastOrDefault())
                {
                    case LineSegment line:
                        return line.Point;
                    case ArcSegment arc:
                        return arc.Point;
                    case CubicBezierSegment cubic:
                        return cubic.Point3;
                    case QuadraticBezierSegment quadratic:
                        return quadratic.Point2;
                    default:
                    case null:
                        return figure.StartPoint;
                }
            }
            throw new Exception("Can not find valid last point from path.");
        }

        /// <summary>
        /// Initializes working path.
        /// </summary>
        /// <param name="start">The path start point.</param>
        public void InitializeWorkingPath(IPointShape start)
        {
            var factory = _serviceProvider.GetService<IFactory>();
            var editor = _serviceProvider.GetService<IProjectEditor>();

            Geometry = factory.CreatePathGeometry(
                ImmutableArray.Create<IPathFigure>(),
                editor.Project.Options.DefaultFillRule);<commit_msg>Update ToolPath.cs<commit_after>﻿using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Core2D.Editor.Input;
using Core2D.Editor.Tools.Path;
using Core2D.Editor.Tools.Settings;
using Core2D.Interfaces;
using Core2D.Path;
using Core2D.Path.Segments;
using Core2D.Shapes;
using Core2D.Style;

namespace Core2D.Editor.Tools
{
    /// <summary>
    /// Path tool.
    /// </summary>
    public class ToolPath : ObservableObject, IEditorTool
    {
        private readonly IServiceProvider _serviceProvider;
        private ToolSettingsPath _settings;
        private readonly PathToolLine _pathToolLine;
        private readonly PathToolArc _pathToolArc;
        private readonly PathToolCubicBezier _pathToolCubicBezier;
        private readonly PathToolQuadraticBezier _pathToolQuadraticBezier;
        private readonly PathToolMove _pathToolMove;

        /// <summary>
        /// Gets or sets flag indicating whether path was initialized.
        /// </summary>
        internal bool IsInitialized { get; set; }

        /// <summary>
        /// Gets or sets current path.
        /// </summary>
        internal IPathShape Path { get; set; }

        /// <summary>
        /// Gets or sets current geometry.
        /// </summary>
        internal IPathGeometry Geometry { get; set; }

        /// <summary>
        /// Gets or sets current geometry context.
        /// </summary>
        internal IGeometryContext GeometryContext { get; set; }

        /// <summary>
        /// Gets or sets previous path tool.
        /// </summary>
        internal IPathTool PreviousPathTool { get; set; }

        /// <inheritdoc/>
        public string Title => "Path";

        /// <summary>
        /// Gets or sets the tool settings.
        /// </summary>
        public ToolSettingsPath Settings
        {
            get => _settings;
            set => Update(ref _settings, value);
        }

        /// <summary>
        /// Initialize new instance of <see cref="ToolPath"/> class.
        /// </summary>
        /// <param name="serviceProvider">The service provider.</param>
        public ToolPath(IServiceProvider serviceProvider) : base()
        {
            _serviceProvider = serviceProvider;
            _settings = new ToolSettingsPath();
            _pathToolLine = serviceProvider.GetService<PathToolLine>();
            _pathToolArc = serviceProvider.GetService<PathToolArc>();
            _pathToolCubicBezier = serviceProvider.GetService<PathToolCubicBezier>();
            _pathToolQuadraticBezier = serviceProvider.GetService<PathToolQuadraticBezier>();
            _pathToolMove = serviceProvider.GetService<PathToolMove>();
            IsInitialized = false;
        }

        /// <inheritdoc/>
        public override object Copy(IDictionary<object, object> shared)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Remove last <see cref="PathSegment"/> segment from the previous figure.
        /// </summary>
        /// <typeparam name="T">The type of the path segment to remove.</typeparam>
        public void RemoveLastSegment<T>() where T : PathSegment
        {
            var figure = Geometry?.Figures.LastOrDefault();
            if (figure != null)
            {
                if (figure.Segments.LastOrDefault() is T segment)
                {
                    figure.Segments = figure.Segments.Remove(segment);
                }
            }
        }

        /// <summary>
        /// Remove last segment from the previous figure.
        /// </summary>
        public void RemoveLastSegment()
        {
            if (PreviousPathTool == _pathToolLine)
            {
                RemoveLastSegment<LineSegment>();
                _pathToolLine.Reset();
            }
            else if (PreviousPathTool == _pathToolArc)
            {
                RemoveLastSegment<ArcSegment>();
                _pathToolArc.Reset();
            }
            else if (PreviousPathTool == _pathToolCubicBezier)
            {
                RemoveLastSegment<CubicBezierSegment>();
                _pathToolCubicBezier.Reset();
            }
            else if (PreviousPathTool == _pathToolQuadraticBezier)
            {
                RemoveLastSegment<QuadraticBezierSegment>();
                _pathToolQuadraticBezier.Reset();
            }

            var editor = _serviceProvider.GetService<IProjectEditor>();
            editor.Project.CurrentContainer.WorkingLayer.Invalidate();
            editor.Project.CurrentContainer.HelperLayer.Invalidate();
        }

        /// <summary>
        /// Gets last point in the current path.
        /// </summary>
        /// <returns>The last path point.</returns>
        public IPointShape GetLastPathPoint()
        {
            var figure = Geometry.Figures.LastOrDefault();
            if (figure != null)
            {
                return (figure.Segments.LastOrDefault()) switch
                {
                    LineSegment line => line.Point,
                    ArcSegment arc => arc.Point,
                    CubicBezierSegment cubic => cubic.Point3,
                    QuadraticBezierSegment quadratic => quadratic.Point2,
                    _ => figure.StartPoint,
                };
            }
            throw new Exception("Can not find valid last point from path.");
        }

        /// <summary>
        /// Initializes working path.
        /// </summary>
        /// <param name="start">The path start point.</param>
        public void InitializeWorkingPath(IPointShape start)
        {
            var factory = _serviceProvider.GetService<IFactory>();
            var editor = _serviceProvider.GetService<IProjectEditor>();

            Geometry = factory.CreatePathGeometry(
                ImmutableArray.Create<IPathFigure>(),
                editor.Project.Options.DefaultFillRule);
{'fraction_non_alphanumeric': 0.09839873890317763, 'fraction_numerical': 0.0018252717165850826, 'mean_word_length': 1.7358147980027236, 'pattern_counts': {'":': 0, '<': 105, '<?xml version=': 0, '>': 116, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5546004', 'n_tokens_mistral': 3012, 'n_tokens_neox': 2878, 'n_words': 701}