<commit_before>﻿namespace EasyButtons.Editor
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;
    using UnityEditor;
    using UnityEngine;
    using Object = UnityEngine.Object;

    internal class Button
    {
        private readonly string _name;
        private readonly ButtonSpacing _spacing;
        private readonly bool _enabled;
        private readonly bool _hasParams;
        private readonly MethodInfo _method;
        private readonly ParamInfo[] _parameters;

        private bool _expanded;

        public Button(MethodInfo method, ButtonAttribute buttonAttribute)
        {
            _name = string.IsNullOrEmpty(buttonAttribute.Name)
                ? ObjectNames.NicifyVariableName(method.Name)
                : buttonAttribute.Name;

            _spacing = buttonAttribute.Spacing;

            bool inAppropriateMode = EditorApplication.isPlaying
                ? buttonAttribute.Mode == ButtonMode.EnabledInPlayMode
                : buttonAttribute.Mode == ButtonMode.DisabledInPlayMode;

            _enabled = buttonAttribute.Mode == ButtonMode.AlwaysEnabled || inAppropriateMode;

            var parameters = method.GetParameters();
            _hasParams = parameters.Length != 0;
            _parameters = parameters.Select(parameter => new ParamInfo(parameter)).ToArray();
            _method = method;
        }

        public void Draw(IEnumerable<Object> targets)
        {
            DrawWithEnabledGUI(_enabled, () =>
            {
                if (_hasParams)
                {
                    DrawFoldout();
                }
                else
                {
                    DrawButtonWithSpacing(targets);
                }
            });
        }

        private void Invoke(IEnumerable<Object> objects)
        {
            var paramValues = _hasParams ? _parameters.Select(param => param.Value).ToArray() : null;

            foreach (Object obj in objects)
            {
                _method.Invoke(obj, paramValues);
            }
        }

        private void DrawButtonWithSpacing(IEnumerable<Object> targets)
        {
            const float spacingHeight = 10f;

            if (_spacing.HasFlag(ButtonSpacing.Before))
                GUILayout.Space(spacingHeight);

            if (GUILayout.Button(_name))
                Invoke(targets);

            if (_spacing.HasFlag(ButtonSpacing.After))
                GUILayout.Space(spacingHeight);
        }

        private void DrawFoldout()
        {
            _expanded = DrawInFoldout(_expanded, _name, () =>
            {
                foreach (ParamInfo param in _parameters)
                {
                    param.Draw();
                }
            });
        }

        private static void DrawWithEnabledGUI(bool enabled, Action drawStuff)
        {
            bool previousValue = GUI.enabled;
            GUI.enabled = enabled;
            drawStuff();
            GUI.enabled = previousValue;
        }

        private static bool DrawInFoldout(bool expanded, string name, Action drawStuff)
        {
            var foldoutRect = GUILayoutUtility.GetRect(new GUIContent(name), EditorStyles.foldoutHeader);

            var buttonRect = new Rect(foldoutRect.xMax - 50f, foldoutRect.y, 50f, foldoutRect.height);
            var actualFoldoutRect = new Rect(foldoutRect.position, new Vector2(foldoutRect.width - 50f, foldoutRect.height));

            expanded = EditorGUI.BeginFoldoutHeaderGroup(actualFoldoutRect, expanded, name);

            if (expanded)
            {
                EditorGUI.indentLevel++;
                drawStuff();
                EditorGUI.indentLevel--;
            }

            EditorGUILayout.EndFoldoutHeaderGroup();

            if (GUI.Button(buttonRect, "Invoke"))
                Debug.Log("invoked");

            return expanded;
        }

        private readonly struct ParamInfo
        {<commit_msg>Made the foldout button take parameters as input<commit_after>﻿namespace EasyButtons.Editor
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;
    using UnityEditor;
    using UnityEngine;
    using Object = UnityEngine.Object;

    internal class Button
    {
        private readonly string _name;
        private readonly ButtonSpacing _spacing;
        private readonly bool _enabled;
        private readonly bool _hasParams;
        private readonly MethodInfo _method;
        private readonly ParamInfo[] _parameters;

        private bool _expanded;

        public Button(MethodInfo method, ButtonAttribute buttonAttribute)
        {
            _name = string.IsNullOrEmpty(buttonAttribute.Name)
                ? ObjectNames.NicifyVariableName(method.Name)
                : buttonAttribute.Name;

            _spacing = buttonAttribute.Spacing;

            bool inAppropriateMode = EditorApplication.isPlaying
                ? buttonAttribute.Mode == ButtonMode.EnabledInPlayMode
                : buttonAttribute.Mode == ButtonMode.DisabledInPlayMode;

            _enabled = buttonAttribute.Mode == ButtonMode.AlwaysEnabled || inAppropriateMode;

            var parameters = method.GetParameters();
            _hasParams = parameters.Length != 0;
            _parameters = parameters.Select(parameter => new ParamInfo(parameter)).ToArray();
            _method = method;
        }

        public void Draw(IEnumerable<Object> targets)
        {
            DrawWithEnabledGUI(_enabled, () =>
            {
                DrawWithSpacing(_spacing.HasFlag(ButtonSpacing.Before), _spacing.HasFlag(ButtonSpacing.After), () =>
                {
                    if (_hasParams)
                    {
                        (Rect foldoutRect, Rect buttonRect) = GetFoldoutAndButtonRects(_name);

                        _expanded = DrawInFoldout(foldoutRect, _expanded, _name, () =>
                        {
                            foreach (ParamInfo param in _parameters)
                            {
                                param.Draw();
                            }
                        });

                        if (GUI.Button(buttonRect, "Invoke"))
                            Invoke(targets);
                    }
                    else
                    {
                        if (GUILayout.Button(_name))
                            Invoke(targets);
                    }
                });
            });
        }

        private static bool DrawInFoldout(Rect foldoutRect, bool expanded, string header, Action drawStuff)
        {
            expanded = EditorGUI.BeginFoldoutHeaderGroup(foldoutRect, expanded, header);

            if (expanded)
            {
                EditorGUI.indentLevel++;
                drawStuff();
                EditorGUI.indentLevel--;
            }

            EditorGUILayout.EndFoldoutHeaderGroup();

            return expanded;
        }

        private static (Rect, Rect) GetFoldoutAndButtonRects(string header)
        {
            const float buttonWidth = 60f;

            var foldoutWithoutButton = GUILayoutUtility.GetRect(new GUIContent(header), EditorStyles.foldoutHeader); // TODO: replace new GUIContent

            var foldoutRect = new Rect(
                foldoutWithoutButton.x,
                foldoutWithoutButton.y,
                foldoutWithoutButton.width - buttonWidth,
                foldoutWithoutButton.height);

            var buttonRect = new Rect(
                foldoutWithoutButton.xMax - buttonWidth,
                foldoutWithoutButton.y,
                buttonWidth,
                foldoutWithoutButton.height);

            return (foldoutRect, buttonRect);
        }

        private void Invoke(IEnumerable<Object> objects)
        {
            var paramValues = _hasParams ? _parameters.Select(param => param.Value).ToArray() : null;

            foreach (Object obj in objects)
            {
                _method.Invoke(obj, paramValues);
            }
        }

        private static void DrawWithSpacing(bool before, bool after, Action drawStuff)
        {
            const float spacingHeight = 10f;

            if (before)
                GUILayout.Space(spacingHeight);

            drawStuff();

            if (after)
                GUILayout.Space(spacingHeight);
        }

        private static void DrawWithEnabledGUI(bool enabled, Action drawStuff)
        {
            bool previousValue = GUI.enabled;
            GUI.enabled = enabled;
            drawStuff();
            GUI.enabled = previousValue;
        }

        private readonly struct ParamInfo
        {
{'fraction_non_alphanumeric': 0.07408262174013386, 'fraction_numerical': 0.0017309023771059312, 'mean_word_length': 1.6184290030211481, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 17, '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': '109447', 'n_tokens_mistral': 2151, 'n_tokens_neox': 2010, 'n_words': 441}