using Microsoft.Xna.Framework;
using MonoGame.FourEngine;
using System;

namespace Raycast.Win32.Entities
{
    partial class Enemy
    {
        protected class RushState : EnemyStateBase
        {
            public const float RushLength = 4f;
            public const float SpeedModifier = 3f;

            public Point Target { get; set; }

            private static readonly Random Random = new Random(DateTime.UtcNow.Millisecond);

            private float _distanceLeft;

            public RushState(Enemy enemy) : base(enemy)
            {
            }

            public override void OnEnter()
            {
                Enemy.Frame = new Point(Enemy.Frame.X, Enemy.AnimationMap[EnemyState.Rush].Start);
                
                var direction = Target.ToVector2() + new Vector2(0.5f) - Enemy.Position;
                _distanceLeft = Math.Abs(direction.Length());
                Enemy.Orientation = direction.OrientTo();
                direction.Normalize();
                Enemy.Direction = direction;

                _distanceLeft = RushLength;

                Enemy.OnAttack();
            }

            public override void OnUpdate(UpdateEventArgs args)
            {
                if (Enemy.Scene == null) return;

                Enemy.VerticalPosition = Enemy.MinVerticalPosition;

                bool CheckMove(float moveX, float moveY)
                {
                    var vector = new Vector2(moveX, moveY);
                    var point = vector.ToPoint();
                    return Pathfinding.CanPassThrough(point);
                }

                var position = Enemy.Position + Enemy.Direction * Enemy.Speed * SpeedModifier;

                var diff = position - Enemy.Position;
                var radius = new Vector2(
                    diff.X > 0 ? Enemy.Radius : -Enemy.Radius, 
                    diff.Y > 0 ? Enemy.Radius : -Enemy.Radius);

                var oldPosition = Enemy.Position;

                if (CheckMove(position.X + radius.X, Enemy.Position.Y + Enemy.Radius) &&
                    CheckMove(position.X + radius.X, Enemy.Position.Y - Enemy.Radius))
                    Enemy.Position = new Vector2(position.X, Enemy.Position.Y);

                if (CheckMove(Enemy.Position.X + Enemy.Radius, position.Y + radius.Y) &&
                    CheckMove(Enemy.Position.X - Enemy.Radius, position.Y + radius.Y))
                    Enemy.Position = new Vector2(Enemy.Position.X, position.Y);
                
                diff = Enemy.Position - oldPosition;
                var length = Math.Abs(diff.Length());
                _distanceLeft -= length;

                if (_distanceLeft <= 0 || length <= Enemy.Speed * 0.75f)
                {
                    GoToNextState();
                }

                diff = Enemy.Scene.Player.Position - Enemy.Position;
                if (Math.Abs(diff.Length()) <= Enemy.Radius * 2)
                {
                    Enemy.Scene.Player.Hurt(3);
                    GoToNextState();
                }
            }
        }
    }
}