using Microsoft.Xna.Framework;
using MonoGame.FourEngine;
using MonoGame.FourEngine.Components;
using MonoGame.FourEngine.Interfaces;
using MonoGame.FourEngine.Raycast;
using MonoGame.FourEngine.Resources;
using Raycast.Win32.Scenes;
using System;

namespace Raycast.Win32.Entities
{
    public class Spawner : RaycastObject, IHaveSizeAndPosition
    {
        public static readonly Point Size = new Point(75, 90);

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

        protected override SpriteDefinition SpriteDefinition
            => new SpriteDefinition
            {
                FileName = Resources.Sprites.Teleport,
                Size = Size
            };

        private RenderedScene _scene;

        private double _msPassed;

        public Spawner()
        {
            Frame = new Point(5, 0);
            VerticalPosition = 0.14f;
            Components.Add(new ActionComponent(OnUpdate));
        }

        private void OnUpdate(UpdateEventArgs args)
        {
            if (_scene == null) return;

            if (Frame.X != 5)
            {
                _msPassed += args.DeltaTime.TotalMilliseconds;
                Frame = new Point((int)(_msPassed / 128), 0);
            }
            else if (Random.NextDouble() < Configuration.SpawnChance && _scene?.Player?.Health > 0)
            {
                _msPassed = 0;
                Frame = new Point(0, 0);
                Spawn();
            }
        }

        private void Spawn()
        {
            var enemy = Random.NextDouble() > 0.75d ? (Enemy)new Fatty() : new Skull();
            enemy.Position = Position;

            _scene.AddEntity(enemy);
        }

        public override void OnAttach(Scene scene)
        {
            _scene = scene as RenderedScene;
        }

        public override void OnDetach(Scene scene)
        {
            _scene = null;
        }

        #region IHaveSizeAndPosition
        Point IHaveSizeAndPosition.Position
        {
            get => Position.ToPoint();
            set => Position = value.ToVector2();
        }
        int IHaveSizeAndPosition.Width { get; set; }
        int IHaveSizeAndPosition.Height { get; set; }
        #endregion

        #region IHaveReadOnlySizeAndPosition
        Point IHaveReadOnlySizeAndPosition.Position => ((IHaveSizeAndPosition)this).Position;
        int IHaveReadOnlySizeAndPosition.Width => ((IHaveSizeAndPosition)this).Width;
        int IHaveReadOnlySizeAndPosition.Height => ((IHaveSizeAndPosition)this).Height;
        #endregion
    }
}