using System.Collections.Generic;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Effects;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Input.Events;
using osuTK;
using osuTK.Graphics;
using osuTK.Input;

namespace AWBWApp.Game.UI.Interrupts
{
    public abstract partial class SideInterupt : BaseInterrupt
    {
        public const float ENTER_DURATION = 500;
        public const float EXIT_DURATION = 200;

        private readonly float animationBaseXOffset = -50f;

        private readonly Container content;
        private readonly FillFlowContainer interactablesContainer;
        private readonly FillFlowContainer headingContainer;
        private readonly TextFlowContainer header;
        private readonly TextFlowContainer body;

        private string headerText;

        public string HeaderText
        {
            get => headerText;
            set
            {
                if (headerText == value)
                    return;
                headerText = value;
                header.Text = value;
            }
        }

        private string bodyText;

        public string BodyText
        {
            get => bodyText;
            set
            {
                if (bodyText == value)
                    return;
                bodyText = value;
                body.Text = value;
            }
        }

        private Vector2 baseSpacing;

        public Vector2 InteractablesSpacing
        {
            get => baseSpacing;
            set
            {
                baseSpacing = value;

                if (State.Value == Visibility.Visible)
                    interactablesContainer.Spacing = baseSpacing;
            }
        }

        protected override bool StartHidden => true;

        public SideInterupt()
        {
            RelativeSizeAxes = Axes.Both;

            Children = new Drawable[]
            {
                content = new Container
                {
                    RelativeSizeAxes = Axes.Both,
                    Alpha = 0f,
                    Children = new Drawable[]
                    {
                        new Container
                        {
                            RelativeSizeAxes = Axes.Both,
                            Masking = true,
                            EdgeEffect = new EdgeEffectParameters
                            {
                                Type = EdgeEffectType.Shadow,
                                Colour = Color4.Black.Opacity(0.5f),
                                Radius = 8,
                            },
                            Children = new Drawable[]
                            {
                                new Box
                                {
                                    RelativeSizeAxes = Axes.Both,
                                    Colour = Color4Extensions.FromHex(@"221a21"),
                                },
                            },
                        },
                        headingContainer = new FillFlowContainer
                        {
                            Anchor = Anchor.Centre,
                            Origin = Anchor.BottomCentre,
                            RelativeSizeAxes = Axes.X,
                            AutoSizeAxes = Axes.Y,
                            Direction = FillDirection.Vertical,
                            Spacing = new Vector2(0f, 10f),
                            Padding = new MarginPadding { Bottom = 10 },
                            Position = new Vector2(0f, -0.1f),
                            RelativePositionAxes = Axes.Y,
                            Children = new Drawable[]
                            {
                                header = new TextFlowContainer(t => t.Font = t.Font.With(size: 25))
                                {
                                    Origin = Anchor.TopCentre,
                                    Anchor = Anchor.TopCentre,
                                    RelativeSizeAxes = Axes.X,
                                    AutoSizeAxes = Axes.Y,
                                    TextAnchor = Anchor.TopCentre,
                                },
                                body = new TextFlowContainer(t => t.Font = t.Font.With(size: 18))
                                {
                                    Origin = Anchor.TopCentre,
                                    Anchor = Anchor.TopCentre,
                                    TextAnchor = Anchor.TopCentre,
                                    RelativeSizeAxes = Axes.X,
                                    AutoSizeAxes = Axes.Y,
                                },
                            },
                        },
                        interactablesContainer = new FillFlowContainer
                        {
                            Anchor = Anchor.Centre,
                            Origin = Anchor.TopCentre,
                            RelativeSizeAxes = Axes.X,
                            Position = new Vector2(0f, -0.1f),
                            RelativePositionAxes = Axes.Y,
                            AutoSizeAxes = Axes.Y,
                            Direction = FillDirection.Vertical,
                        },
                    },
                },
            };

            Show();
        }

        protected void SetInteractables(IEnumerable<Drawable> range)
        {
            interactablesContainer.ChildrenEnumerable = range;
        }

        protected void SetInnerPositionOffsets(Vector2 offset)
        {
            headingContainer.Position = offset;
            interactablesContainer.Position = offset;
        }

        protected override bool ContentIsOpen()
        {
            return content.IsPresent;
        }

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

            if (content.Alpha == 0)
            {
                interactablesContainer.TransformSpacingTo(new Vector2(animationBaseXOffset, baseSpacing.Y));
                interactablesContainer.MoveToX(animationBaseXOffset);
            }

            content.FadeIn(ENTER_DURATION, Easing.OutQuint);
            this.MoveToX(animationBaseXOffset).MoveToX(0, ENTER_DURATION, Easing.OutQuint);

            interactablesContainer.TransformSpacingTo(baseSpacing, ENTER_DURATION, Easing.OutQuint);
            interactablesContainer.MoveToX(0, ENTER_DURATION, Easing.OutQuint);
        }

        protected override void PopOut()
        {
            base.PopOut();
            content.FadeOut(EXIT_DURATION, Easing.InSine);
            this.MoveToX(0).MoveToX(animationBaseXOffset, ENTER_DURATION, Easing.OutQuint);

            interactablesContainer.TransformSpacingTo(new Vector2(animationBaseXOffset, baseSpacing.Y), ENTER_DURATION, Easing.OutQuint);
            interactablesContainer.MoveToX(animationBaseXOffset, ENTER_DURATION, Easing.OutQuint);
        }

        protected override bool OnClick(ClickEvent e)
        {
            return true;
        }

        protected override bool OnKeyDown(KeyDownEvent e)
        {
            if (e.Key == Key.Escape)
            {
                Cancel();
                return true;
            }

            return base.OnKeyDown(e);
        }
    }
}
