using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SFML.Graphics;
using SFML.Window;
using YourBeatingHeart.Main.Helper;

namespace YourBeatingHeart.Main.States.Play.Entities
{
    public abstract class Item : PlayStateEntity
    {
        public ItemType Type { get; private set; }

        // player who last threw this item
        public Player owner;

        protected Vector2f Velocity;
        protected Vector2f Direction;
        protected Drawable Drawable;
        private float width;
        private float height;
        public FloatRect CollisionRect { get { return new FloatRect(Position.X - width / 2, Position.Y - height, width, height); } }

        protected Item(PlayState playState, Vector2f position, Drawable drawable, float width, float height, ItemType type)
            : base(playState, position)
        {
            Velocity = new Vector2f(0, 0);
            Direction = new Vector2f(0, 0);
            Drawable = drawable;
            Type = type;
            this.width = width;
            this.height = height;
            Layer = PlayState.Layers.Items;
        }

        public override void Update(float elapsedTime)
        {
            Velocity.Y += Constants.GRAVITY * elapsedTime;
            float dx = Velocity.X * elapsedTime;
            float dy = Velocity.Y * elapsedTime;

            float width = CollisionRect.Width;
            float height = CollisionRect.Height;
            Vector2f actualMove = playState.CollisionManager.Restrict(
                new FloatRect(Position.X - width / 2, Position.Y - height, width, height), 
                new Vector2f(dx, dy)
            );

            if (actualMove.Y != dy)
                BounceV();

            if (actualMove.X != dx)
                BounceH();

            Move(actualMove.X, actualMove.Y);

            Player player = playState.CollisionManager.PlayerCollision(CollisionRect);
            if (player != null)
            {
                OnPlayerCollision(player);
            }
        }

        public override void Draw(RenderTarget renderTarget)
        {
            renderTarget.Draw(Drawable);
        }

        public virtual void Throw(Vector2f dir)
        {
            Velocity = dir.GetNormalized() * Constants.THROW_IMPULSE;
        }

        /** Bounce vertically, when colliding with the ground. */
        public void BounceV()
        {
            // if we are below the threshold, just stay there
            if (Math.Abs(Velocity.Y) < Constants.ITEM_BUMP_THRESHOLD)
            {
                Velocity.X = 0;
                Velocity.Y = 0;
                owner = null;
            }
            else
            {
                // if we hit the ground, bounce back up
                Velocity.Y = -Velocity.Y * Constants.ITEM_BUMPINESS;
                Velocity.X *= Constants.GROUND_FRICTION;
            }
        }

        /** Bounce horizontally, when colliding with a horizontal object. */
        public void BounceH()
        {
            // if we hit the screen edge, bounce back
            Velocity.X = -Velocity.X;
        }

        public abstract void OnPlayerCollision(Player player);
    }
}
