<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace ATP.AnimationPathTools.AnimatorComponent {

    public sealed class PathData : ScriptableObject {
        #region EVENTS

        public event EventHandler<NodeAddedRemovedEventArgs> NodeAdded;

        public event EventHandler NodePositionChanged;

        public event EventHandler<NodeAddedRemovedEventArgs> NodeRemoved;

        //public event EventHandler TiltingCurveUpdated;

        public event EventHandler PathTimestampsChanged;

        public event EventHandler PathReset;

        public event EventHandler RotationPathReset;

        public event EventHandler RotationPointPositionChanged;

        public event EventHandler NodeTangentsChanged;

        /// <summary>
        /// Event called after a key was added, removed or moved in the ease curve.
        /// </summary>
        public event EventHandler EaseCurveUpdated;

        /// <summary>
        /// Event called after a key was added, removed or moved in the tilting curve.
        /// </summary>
        public event EventHandler TiltingCurveUpdated;

        #endregion EVENTS

        #region CONST

        private const float DefaultEaseCurveValue = 0.05f;
        private const float DefaultTiltingCurveValue = 0.001f;
        private const float DefaultSmoothWeight = 0;
        /// <summary>
        /// Sampling used to calculate path length.
        /// </summary>
        private const int PathLengthSampling = 5;
        /// <summary>
        /// Default sampling used to calculate path lenght.
        /// </summary>
        //private const int PathLengthSampling = 40;

        #endregion

        #region FIELDS

        [SerializeField]
        private AnimationPath animatedObjectPath;

        [SerializeField]
        private AnimationCurve easeCurve;

        [SerializeField]
        private AnimationPath rotationPath;

        [SerializeField]
        private AnimationCurve tiltingCurve;

        [SerializeField]
        private List<bool> easeToolState;

        [SerializeField]
        private List<bool> tiltingToolState;

        #endregion FIELDS

        #region PROPERTIES

        public int EaseCurveKeysNo {
            get { return EaseCurve.length; }
        }

        public int NodesNo {
            get { return animatedObjectPath[0].length; }
        }

        public int RotationPathNodesNo {
            get { return RotationPath.KeysNo; }
        }

        public int TiltingCurveKeysNo {
            get { return TiltingCurve.length; }
        }

        private AnimationPath AnimatedObjectPath {
            get { return animatedObjectPath; }
        }

        public AnimationCurve EaseCurve {
            get { return easeCurve; }
            set { easeCurve = value; }
        }

        private AnimationPath RotationPath {
            get { return rotationPath; }
        }

        public AnimationCurve TiltingCurve {
            get { return tiltingCurve; }
            set { tiltingCurve = value; }
        }

        /// <summary>
        /// List with with indexes of nodes that have ease value assigned.
        /// </summary>
        public List<bool> EaseToolState {
            get { return easeToolState; }
            set { easeToolState = value; }
        }

        /// <summary>
        /// List with with indexes of nodes that have tilting value assigned.
        /// </summary>
        public List<bool> TiltingToolState {
            get { return tiltingToolState; }
            set { tiltingToolState = value; }
        }
        #endregion PROPERTIES

        #region UNITY MESSAGES

        private void OnEnable() {
            HandleInitializeReferenceTypes();
            SubscribeToEvents();
        }


        private void OnDisable() {
            UnsubscribeFromEvents();
        }

        private void UnsubscribeFromEvents() {
            NodeAdded -= PathData_NodeAdded;
            NodeRemoved -= PathData_NodeRemoved;
            TiltingCurveUpdated -= PathData_TiltingCurveUpdated;
            EaseCurveUpdated -= PathData_TiltingCurveUpdated;
            PathTimestampsChanged -= PathData_PathTimestampsChanged;
            NodePositionChanged -= PathData_NodePositionChanged;
        }

        #endregion UNITY MESSAGES

        #region EVENT INVOCATORS

        private void OnNodeAdded(int nodeIndex) {
            var nodeTimestamp = GetNodeTimestamp(nodeIndex);
            var args = new NodeAddedRemovedEventArgs(nodeIndex, nodeTimestamp);

            var handler = NodeAdded;
            if (handler != null) handler(this, args);
        }

        private void OnNodePositionChanged() {
            var handler = NodePositionChanged;
            if (handler != null) handler(this, EventArgs.Empty);
        }

        private void OnNodeRemoved(int nodeIndex) {
            var nodeTimestamp = GetNodeTimestamp(nodeIndex);
            var args = new NodeAddedRemovedEventArgs(nodeIndex, nodeTimestamp);

            var handler = NodeRemoved;
            if (handler != null) handler(this, args);
        }

        private void OnTiltingCurveUpdated() {
            var handler = TiltingCurveUpdated;
            if (handler != null) handler(this, EventArgs.Empty);
        }

        private void OnNodeTimeChanged() {
            var handler = PathTimestampsChanged;
            if (handler != null) handler(this, EventArgs.Empty);
        }

        private void OnPathReset() {
            var handler = PathReset;
            if (handler != null) handler(this, EventArgs.Empty);
        }

        private void OnRotationPathReset() {
            var handler = RotationPathReset;
            if (handler != null) handler(this, EventArgs.Empty);
        }

        private void OnRotationPointPositionChanged() {
            var handler = RotationPointPositionChanged;
            if (handler != null) handler(this, EventArgs.Empty);
        }

        #endregion EVENT INVOCATORS

        #region EVENT HANDLERS

        private void PathData_NodeAdded(object sender, NodeAddedRemovedEventArgs e) {
            // todo replace with assert
            // Compare number of nodes with predicted number of elements in the list.
            if (NodesNo != EaseToolState.Count + 1) {
                throw new Exception("This operation will cause a list to have" +
                                    "more entries then there's nodes in the" +
                                    "path");
            }

            EaseToolState.Insert(e.NodeIndex, false);
            TiltingToolState.Insert(e.NodeIndex, false);
            //Debug.Log("Node added to list: " + e.NodeIndex
            //    + " Current tilting entries: " + TiltingToolState.Count);
        }

        private void PathData_NodePositionChanged(object sender, EventArgs e) {
        }

        private void PathData_NodeRemoved(object sender, NodeAddedRemovedEventArgs e) {
            // todo replace with assert
            // Compare number of nodes with predicted number of elements in the list.
            if (NodesNo != EaseToolState.Count - 1) {
                throw new Exception("This operation will cause a list to have" +
                                    " more entries then there's nodes in the" +
                                    " path");
            }

            EaseToolState.RemoveAt(e.NodeIndex);
            TiltingToolState.RemoveAt(e.NodeIndex);
            HandleRemoveNodeTools(e.NodeTimestamp);
            //Debug.Log("Node removed from list: " + e.NodeIndex
            //    + " Current tilting entries: " + TiltingToolState.Count);
        }

        /// <summary>
        /// Handles removal path node tools for a give node index.
        /// </summary>
        /// <param name="nodeIndex">Path node index.</param>
        /// <param name="nodeTimestamp">Path node timestamp.</param>
        private void HandleRemoveNodeTools(float nodeTimestamp) {
            HandleDisableEaseTool(nodeTimestamp);
            HandleRemoveTiltingTool(nodeTimestamp);
        }

        /// <summary>
        /// Removes tilting value for a given path node index.
        /// </summary>
        /// <param name="nodeIndex">Path node index.</param>
        /// <param name="nodeTimestamp">Path node timestamp.</param>
        // todo rename to HandleDisableTiltingTool
        private void HandleRemoveTiltingTool(float nodeTimestamp) {
            // Get nodes that have tilitng tool enabled.
            var tiltedNodesTimestamps = Utilities.GetAnimationCurveTimestamps(TiltingCurve);
            // Find ease index for the given timestamp.
            var tiltingKeyIndex = tiltedNodesTimestamps.FindIndex(x => x == nodeTimestamp);

            // Remove key from ease curve.
            if (tiltingKeyIndex != -1) {
                TiltingCurve.RemoveKey(tiltingKeyIndex);
            }

            Utilities.Assert(
                () => TiltingCurve.length == tiltedNodesTimestamps.Count,
                String.Format("Number of tilting curve keys and number of nodes" +
                              " with enabled tilting tool differs.\n" +
                              "Tilting curve length: {0}\n" +
                              "Nodes with enabled ease tool: {1}",<commit_msg>Rename method<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace ATP.AnimationPathTools.AnimatorComponent {

    public sealed class PathData : ScriptableObject {
        #region EVENTS

        public event EventHandler<NodeAddedRemovedEventArgs> NodeAdded;

        public event EventHandler NodePositionChanged;

        public event EventHandler<NodeAddedRemovedEventArgs> NodeRemoved;

        //public event EventHandler TiltingCurveUpdated;

        public event EventHandler PathTimestampsChanged;

        public event EventHandler PathReset;

        public event EventHandler RotationPathReset;

        public event EventHandler RotationPointPositionChanged;

        public event EventHandler NodeTangentsChanged;

        /// <summary>
        /// Event called after a key was added, removed or moved in the ease curve.
        /// </summary>
        public event EventHandler EaseCurveUpdated;

        /// <summary>
        /// Event called after a key was added, removed or moved in the tilting curve.
        /// </summary>
        public event EventHandler TiltingCurveUpdated;

        #endregion EVENTS

        #region CONST

        private const float DefaultEaseCurveValue = 0.05f;
        private const float DefaultTiltingCurveValue = 0.001f;
        private const float DefaultSmoothWeight = 0;
        /// <summary>
        /// Sampling used to calculate path length.
        /// </summary>
        private const int PathLengthSampling = 5;
        /// <summary>
        /// Default sampling used to calculate path lenght.
        /// </summary>
        //private const int PathLengthSampling = 40;

        #endregion

        #region FIELDS

        [SerializeField]
        private AnimationPath animatedObjectPath;

        [SerializeField]
        private AnimationCurve easeCurve;

        [SerializeField]
        private AnimationPath rotationPath;

        [SerializeField]
        private AnimationCurve tiltingCurve;

        [SerializeField]
        private List<bool> easeToolState;

        [SerializeField]
        private List<bool> tiltingToolState;

        #endregion FIELDS

        #region PROPERTIES

        public int EaseCurveKeysNo {
            get { return EaseCurve.length; }
        }

        public int NodesNo {
            get { return animatedObjectPath[0].length; }
        }

        public int RotationPathNodesNo {
            get { return RotationPath.KeysNo; }
        }

        public int TiltingCurveKeysNo {
            get { return TiltingCurve.length; }
        }

        private AnimationPath AnimatedObjectPath {
            get { return animatedObjectPath; }
        }

        public AnimationCurve EaseCurve {
            get { return easeCurve; }
            set { easeCurve = value; }
        }

        private AnimationPath RotationPath {
            get { return rotationPath; }
        }

        public AnimationCurve TiltingCurve {
            get { return tiltingCurve; }
            set { tiltingCurve = value; }
        }

        /// <summary>
        /// List with with indexes of nodes that have ease value assigned.
        /// </summary>
        public List<bool> EaseToolState {
            get { return easeToolState; }
            set { easeToolState = value; }
        }

        /// <summary>
        /// List with with indexes of nodes that have tilting value assigned.
        /// </summary>
        public List<bool> TiltingToolState {
            get { return tiltingToolState; }
            set { tiltingToolState = value; }
        }
        #endregion PROPERTIES

        #region UNITY MESSAGES

        private void OnEnable() {
            HandleInitializeReferenceTypes();
            SubscribeToEvents();
        }


        private void OnDisable() {
            UnsubscribeFromEvents();
        }

        private void UnsubscribeFromEvents() {
            NodeAdded -= PathData_NodeAdded;
            NodeRemoved -= PathData_NodeRemoved;
            TiltingCurveUpdated -= PathData_TiltingCurveUpdated;
            EaseCurveUpdated -= PathData_TiltingCurveUpdated;
            PathTimestampsChanged -= PathData_PathTimestampsChanged;
            NodePositionChanged -= PathData_NodePositionChanged;
        }

        #endregion UNITY MESSAGES

        #region EVENT INVOCATORS

        private void OnNodeAdded(int nodeIndex) {
            var nodeTimestamp = GetNodeTimestamp(nodeIndex);
            var args = new NodeAddedRemovedEventArgs(nodeIndex, nodeTimestamp);

            var handler = NodeAdded;
            if (handler != null) handler(this, args);
        }

        private void OnNodePositionChanged() {
            var handler = NodePositionChanged;
            if (handler != null) handler(this, EventArgs.Empty);
        }

        private void OnNodeRemoved(int nodeIndex) {
            var nodeTimestamp = GetNodeTimestamp(nodeIndex);
            var args = new NodeAddedRemovedEventArgs(nodeIndex, nodeTimestamp);

            var handler = NodeRemoved;
            if (handler != null) handler(this, args);
        }

        private void OnTiltingCurveUpdated() {
            var handler = TiltingCurveUpdated;
            if (handler != null) handler(this, EventArgs.Empty);
        }

        private void OnNodeTimeChanged() {
            var handler = PathTimestampsChanged;
            if (handler != null) handler(this, EventArgs.Empty);
        }

        private void OnPathReset() {
            var handler = PathReset;
            if (handler != null) handler(this, EventArgs.Empty);
        }

        private void OnRotationPathReset() {
            var handler = RotationPathReset;
            if (handler != null) handler(this, EventArgs.Empty);
        }

        private void OnRotationPointPositionChanged() {
            var handler = RotationPointPositionChanged;
            if (handler != null) handler(this, EventArgs.Empty);
        }

        #endregion EVENT INVOCATORS

        #region EVENT HANDLERS

        private void PathData_NodeAdded(object sender, NodeAddedRemovedEventArgs e) {
            // todo replace with assert
            // Compare number of nodes with predicted number of elements in the list.
            if (NodesNo != EaseToolState.Count + 1) {
                throw new Exception("This operation will cause a list to have" +
                                    "more entries then there's nodes in the" +
                                    "path");
            }

            EaseToolState.Insert(e.NodeIndex, false);
            TiltingToolState.Insert(e.NodeIndex, false);
            //Debug.Log("Node added to list: " + e.NodeIndex
            //    + " Current tilting entries: " + TiltingToolState.Count);
        }

        private void PathData_NodePositionChanged(object sender, EventArgs e) {
        }

        private void PathData_NodeRemoved(object sender, NodeAddedRemovedEventArgs e) {
            // todo replace with assert
            // Compare number of nodes with predicted number of elements in the list.
            if (NodesNo != EaseToolState.Count - 1) {
                throw new Exception("This operation will cause a list to have" +
                                    " more entries then there's nodes in the" +
                                    " path");
            }

            EaseToolState.RemoveAt(e.NodeIndex);
            TiltingToolState.RemoveAt(e.NodeIndex);
            HandleRemoveNodeTools(e.NodeTimestamp);
            //Debug.Log("Node removed from list: " + e.NodeIndex
            //    + " Current tilting entries: " + TiltingToolState.Count);
        }

        /// <summary>
        /// Handles removal path node tools for a give node index.
        /// </summary>
        /// <param name="nodeIndex">Path node index.</param>
        /// <param name="nodeTimestamp">Path node timestamp.</param>
        private void HandleRemoveNodeTools(float nodeTimestamp) {
            HandleDisableEaseTool(nodeTimestamp);
            HandleDisableTiltingTool(nodeTimestamp);
        }

        /// <summary>
        /// Removes tilting value for a given path node index.
        /// </summary>
        /// <param name="nodeIndex">Path node index.</param>
        /// <param name="nodeTimestamp">Path node timestamp.</param>
        private void HandleDisableTiltingTool(float nodeTimestamp) {
            // Get nodes that have tilitng tool enabled.
            var tiltedNodesTimestamps = Utilities.GetAnimationCurveTimestamps(TiltingCurve);
            // Find ease index for the given timestamp.
            var tiltingKeyIndex = tiltedNodesTimestamps.FindIndex(x => x == nodeTimestamp);

            // Remove key from ease curve.
            if (tiltingKeyIndex != -1) {
                TiltingCurve.RemoveKey(tiltingKeyIndex);
            }

            Utilities.Assert(
                () => TiltingCurve.length == tiltedNodesTimestamps.Count,
                String.Format("Number of tilting curve keys and number of nodes" +
                              " with enabled tilting tool differs.\n" +
                              "Tilting curve length: {0}\n" +
                              "Nodes with enabled ease tool: {1}",
{'fraction_non_alphanumeric': 0.07714332018799633, 'fraction_numerical': 0.0018367457187618173, 'mean_word_length': 1.8731957162812354, 'pattern_counts': {'":': 0, '<': 63, '<?xml version=': 0, '>': 67, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7031781', 'n_tokens_mistral': 4594, 'n_tokens_neox': 4470, 'n_words': 1286}