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

using System;
using osu.Framework.Allocation;
using osu.Framework.Extensions.LocalisationExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Localisation;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Screens.OnlinePlay.DailyChallenge.Events;
using osuTK;

namespace osu.Game.Screens.OnlinePlay.DailyChallenge
{
    public partial class DailyChallengeTotalsDisplay : CompositeDrawable
    {
        private Container passCountContainer = null!;
        private TotalRollingCounter passCounter = null!;
        private Container totalScoreContainer = null!;
        private TotalRollingCounter totalScoreCounter = null!;

        private long totalPassCountInstantaneous;
        private long cumulativeTotalScoreInstantaneous;

        [BackgroundDependencyLoader]
        private void load()
        {
            InternalChild = new GridContainer
            {
                RelativeSizeAxes = Axes.Both,
                RowDimensions =
                [
                    new Dimension(GridSizeMode.AutoSize),
                    new Dimension(),
                    new Dimension(GridSizeMode.AutoSize),
                    new Dimension(),
                ],
                Content = new[]
                {
                    new Drawable[]
                    {
                        new SectionHeader("Total pass count")
                    },
                    new Drawable[]
                    {
                        passCountContainer = new Container
                        {
                            RelativeSizeAxes = Axes.Both,
                            Anchor = Anchor.Centre,
                            Origin = Anchor.Centre,
                            Child = passCounter = new TotalRollingCounter
                            {
                                Anchor = Anchor.Centre,
                                Origin = Anchor.Centre,
                            }
                        }
                    },
                    new Drawable[]
                    {
                        new SectionHeader("Cumulative total score")
                    },
                    new Drawable[]
                    {
                        totalScoreContainer = new Container
                        {
                            RelativeSizeAxes = Axes.Both,
                            Anchor = Anchor.Centre,
                            Origin = Anchor.Centre,
                            Child = totalScoreCounter = new TotalRollingCounter
                            {
                                Anchor = Anchor.Centre,
                                Origin = Anchor.Centre,
                            }
                        }
                    },
                }
            };
        }

        public void SetInitialCounts(long totalPassCount, long cumulativeTotalScore)
        {
            totalPassCountInstantaneous = totalPassCount;
            cumulativeTotalScoreInstantaneous = cumulativeTotalScore;
        }

        public void AddNewScore(NewScoreEvent ev)
        {
            totalPassCountInstantaneous += 1;
            cumulativeTotalScoreInstantaneous += ev.TotalScore;
        }

        protected override void Update()
        {
            base.Update();

            passCounter.Current.Value = totalPassCountInstantaneous;
            totalScoreCounter.Current.Value = cumulativeTotalScoreInstantaneous;
        }

        protected override void UpdateAfterChildren()
        {
            base.UpdateAfterChildren();

            var totalPassCountProportionOfParent = Vector2.Divide(passCountContainer.DrawSize, passCounter.DrawSize);
            passCounter.Scale = new Vector2(Math.Min(Math.Min(totalPassCountProportionOfParent.X, totalPassCountProportionOfParent.Y) * 0.8f, 1));

            var totalScoreTextProportionOfParent = Vector2.Divide(totalScoreContainer.DrawSize, totalScoreCounter.DrawSize);
            totalScoreCounter.Scale = new Vector2(Math.Min(Math.Min(totalScoreTextProportionOfParent.X, totalScoreTextProportionOfParent.Y) * 0.8f, 1));
        }

        private partial class TotalRollingCounter : RollingCounter<long>
        {
            protected override double RollingDuration => 1000;

            protected override Easing RollingEasing => Easing.OutPow10;

            protected override bool IsRollingProportional => true;

            protected override double GetProportionalDuration(long currentValue, long newValue)
            {
                long change = Math.Abs(newValue - currentValue);

                if (change < 10)
                    return 0;

                return Math.Min(6000, RollingDuration * Math.Sqrt(change) / 100);
            }

            protected override OsuSpriteText CreateSpriteText() => new OsuSpriteText
            {
                Font = OsuFont.Default.With(size: 80f, fixedWidth: true),
                Spacing = new Vector2(-4, 0)
            };

            protected override LocalisableString FormatCount(long count) => count.ToLocalisableString(@"N0");
        }
    }
}