<commit_before>﻿// Copyright (c) ppy Pty Ltd <<EMAIL>>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using osu.Framework.Allocation;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics;
using osu.Framework.Bindables;
using osu.Game.Online.API.Requests.Responses;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics.Sprites;
using System.Linq;
using osu.Game.Online.API.Requests;
using osu.Game.Online.API;
using System.Collections.Generic;
using osu.Framework.Extensions.IEnumerableExtensions;

namespace osu.Game.Overlays.Comments
{
    public class CommentsPage : CompositeDrawable
    {
        public readonly BindableBool ShowDeleted = new BindableBool();
        public readonly Bindable<CommentsSortCriteria> Sort = new Bindable<CommentsSortCriteria>();
        public readonly Bindable<CommentableType> Type = new Bindable<CommentableType>();
        public readonly BindableLong CommentableId = new BindableLong();

        [Resolved]
        private IAPIProvider api { get; set; }

        private readonly CommentBundle commentBundle;

        public CommentsPage(CommentBundle commentBundle)
        {
            this.commentBundle = commentBundle;
        }

        [BackgroundDependencyLoader]
        private void load(OverlayColourProvider colourProvider)
        {
            FillFlowContainer flow;

            RelativeSizeAxes = Axes.X;
            AutoSizeAxes = Axes.Y;

            AddRangeInternal(new Drawable[]
            {
                new Box
                {
                    RelativeSizeAxes = Axes.Both,
                    Colour = colourProvider.Background5
                },
                flow = new FillFlowContainer
                {
                    RelativeSizeAxes = Axes.X,
                    AutoSizeAxes = Axes.Y,
                    Direction = FillDirection.Vertical,
                }
            });

            if (!commentBundle.Comments.Any())
            {
                flow.Add(new NoCommentsPlaceholder());
                return;
            }

            foreach (var comment in commentBundle.Comments)
            {
                var drawableComment = createDrawableComment(comment);

                var children = commentBundle.Comments.Where(c => c.ParentId == comment.Id);

                if (children.Any())
                {
                    children.ForEach(c =>
                    {
                        c.ParentComment = comment;
                    });
                    drawableComment.OnLoadComplete += loaded => ((DrawableComment)loaded).AddReplies(children.Select(c => createDrawableComment(c)));
                }

                if (comment.IsTopLevel)
                    flow.Add(drawableComment);
            }
        }

        private void onCommentRepliesRequested(DrawableComment drawableComment, int page)
        {
            var request = new GetCommentRepliesRequest(drawableComment.Comment.Id, Type.Value, CommentableId.Value, Sort.Value, page);
            request.Success += response => onCommentRepliesReceived(response, drawableComment);
            api.PerformAsync(request);
        }

        private void onCommentRepliesReceived(CommentBundle response, DrawableComment drawableComment)
        {
            var receivedComments = response.Comments;

            var uniqueComments = new List<Comment>();

            // We may receive already loaded comments
            receivedComments.ForEach(c =>
            {
                if (drawableComment.LoadedReplies.All(loadedReply => loadedReply.Id != c.Id))
                    uniqueComments.Add(c);
            });

            uniqueComments.ForEach(c => c.ParentComment = drawableComment.Comment);

            drawableComment.AddReplies(uniqueComments.Select(comment => createDrawableComment(comment)));
        }

        private DrawableComment createDrawableComment(Comment comment) => new DrawableComment(comment)
        {
            ShowDeleted = { BindTarget = ShowDeleted },
            Sort = { BindTarget = Sort },<commit_msg>CI fix<commit_after>﻿// Copyright (c) ppy Pty Ltd <<EMAIL>>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using osu.Framework.Allocation;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics;
using osu.Framework.Bindables;
using osu.Game.Online.API.Requests.Responses;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics.Sprites;
using System.Linq;
using osu.Game.Online.API.Requests;
using osu.Game.Online.API;
using System.Collections.Generic;
using osu.Framework.Extensions.IEnumerableExtensions;

namespace osu.Game.Overlays.Comments
{
    public class CommentsPage : CompositeDrawable
    {
        public readonly BindableBool ShowDeleted = new BindableBool();
        public readonly Bindable<CommentsSortCriteria> Sort = new Bindable<CommentsSortCriteria>();
        public readonly Bindable<CommentableType> Type = new Bindable<CommentableType>();
        public readonly BindableLong CommentableId = new BindableLong();

        [Resolved]
        private IAPIProvider api { get; set; }

        private readonly CommentBundle commentBundle;

        public CommentsPage(CommentBundle commentBundle)
        {
            this.commentBundle = commentBundle;
        }

        [BackgroundDependencyLoader]
        private void load(OverlayColourProvider colourProvider)
        {
            FillFlowContainer flow;

            RelativeSizeAxes = Axes.X;
            AutoSizeAxes = Axes.Y;

            AddRangeInternal(new Drawable[]
            {
                new Box
                {
                    RelativeSizeAxes = Axes.Both,
                    Colour = colourProvider.Background5
                },
                flow = new FillFlowContainer
                {
                    RelativeSizeAxes = Axes.X,
                    AutoSizeAxes = Axes.Y,
                    Direction = FillDirection.Vertical,
                }
            });

            if (!commentBundle.Comments.Any())
            {
                flow.Add(new NoCommentsPlaceholder());
                return;
            }

            foreach (var comment in commentBundle.Comments)
            {
                var drawableComment = createDrawableComment(comment);

                var children = commentBundle.Comments.Where(c => c.ParentId == comment.Id);

                if (children.Any())
                {
                    children.ForEach(c =>
                    {
                        c.ParentComment = comment;
                    });
                    drawableComment.OnLoadComplete += loaded => ((DrawableComment)loaded).AddReplies(children.Select(createDrawableComment));
                }

                if (comment.IsTopLevel)
                    flow.Add(drawableComment);
            }
        }

        private void onCommentRepliesRequested(DrawableComment drawableComment, int page)
        {
            var request = new GetCommentRepliesRequest(drawableComment.Comment.Id, Type.Value, CommentableId.Value, Sort.Value, page);
            request.Success += response => onCommentRepliesReceived(response, drawableComment);
            api.PerformAsync(request);
        }

        private void onCommentRepliesReceived(CommentBundle response, DrawableComment drawableComment)
        {
            var receivedComments = response.Comments;

            var uniqueComments = new List<Comment>();

            // We may receive already loaded comments
            receivedComments.ForEach(c =>
            {
                if (drawableComment.LoadedReplies.All(loadedReply => loadedReply.Id != c.Id))
                    uniqueComments.Add(c);
            });

            uniqueComments.ForEach(c => c.ParentComment = drawableComment.Comment);

            drawableComment.AddReplies(uniqueComments.Select(createDrawableComment));
        }

        private DrawableComment createDrawableComment(Comment comment) => new DrawableComment(comment)
        {
            ShowDeleted = { BindTarget = ShowDeleted },
            Sort = { BindTarget = Sort },
{'fraction_non_alphanumeric': 0.08114383477942075, 'fraction_numerical': 0.0002444091409018697, 'mean_word_length': 1.9825072886297377, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 35, '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': '5661243', 'n_tokens_mistral': 2080, 'n_tokens_neox': 1963, 'n_words': 423}