using Microsoft.Xna.Framework;
using MonoGame.FourEngine;
using MonoGame.FourEngine.Components;
using MonoGame.FourEngine.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Raycast.Win32.Entities
{
    public partial class Fatty : Enemy
    {
        public override string FileName => Resources.Sprites.Fatty;
        public override Point Size => new Point(135);

        public override float Radius => 0.4f;
        public override float Speed => 0.08f;

        public override IDictionary<EnemyState, Range> AnimationMap =>
            new Dictionary<EnemyState, Range>
            {
                { EnemyState.Idle, new Range(0, 1) },
                { EnemyState.Hurt, new Range(1, 1) },
                { EnemyState.Chase, new Range(3, 6) },
                { EnemyState.Shoot, new Range(8, 1) },
                { EnemyState.Death, new Range(9, 1) },
            };

        private SfxComponent _sfxHurt;
        private SfxComponent _sfxAttack;
        private SfxComponent _sfxDie;

        public Fatty()
        {
            Components.Add(_sfxHurt = new SfxComponent(Resources.Sfx.Fatty1));
            Components.Add(_sfxAttack = new SfxComponent(Resources.Sfx.Fatty2));
            Components.Add(_sfxDie = new SfxComponent(Resources.Sfx.Fatty3));

            Health = 40;
        }

        protected override EnemyState Decide()
        {
            // If we have no health, let's die

            if (Health <= 0 || Scene == null)
            {
                return EnemyState.Death;
            }

            // If player is dead stop attacking

            if (Scene.Player.Health <= 0)
            {
                return EnemyState.Idle;
            }

            // Rush to player to deal damage

            if (State == EnemyState.Chase &&
                Math.Abs((Position - Player.Position).Length()) <= ShootState.ShootLength &&
                !Scene.Entities.Filter<Fatty>().Any(x => x.State == EnemyState.Shoot))
            {
                return EnemyState.Shoot;
            }

            var from = Position.ToPoint();
            var to = Player.Position.ToPoint();

            var step = Pathfinding.NextStep(from, to);

            // Chase the player to get closer

            var chase = (ChaseState)StateHandlers[EnemyState.Chase];

            if (from != step)
            {
                chase.Target = step;
                return EnemyState.Chase;
            }

            // Go to random direction
            chase.Target = from +
                new Point(
                    Random.NextDouble() > 0.5 ? 1 : -1,
                    Random.NextDouble() > 0.5 ? 1 : -1);
            return EnemyState.Chase;
        }

        public override void OnAttack()
        {
            _sfxAttack.Play();
        }

        public override void OnHurt()
        {
            _sfxHurt.Play();
        }

        public override void OnDie()
        {
            _sfxDie.Play();
        }
    }
}