using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
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 Explosion : RaycastObject, IHaveSizeAndPosition, IRecyclable
    {
        public static readonly Point Size = new Point(128);

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

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

        private RenderedScene _scene;

        private double _msPassed;

        private float _maxTime;

        private SfxComponent _sfx;

        public Explosion()
        {
            Components.Add(new ActionComponent(OnUpdate));
            Components.Add(_sfx = new SfxComponent(Resources.Sfx.RocketExplode));
            _maxTime = 128 * Sprite.FrameCount.X;
        }

        public void Recycle()
        {
            Frame = new Point(0, 0);
            _msPassed = 0;
        }

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

            _msPassed += args.DeltaTime.TotalMilliseconds;

            _scene.Player.Update3dSoundEffect(_sfx, Position);

            var frameX = (int)(_msPassed / 128);
            if (frameX < Sprite.FrameCount.X)
            {
                Frame = new Point(frameX, Frame.Y);
            }
            else
            {
                _scene.RemoveEntity(this);
            }
        }

        public override void Draw(SpriteBatch batch, Rectangle destinationRectangle, Rectangle sourceRectangle, Color color)
        {
            var fade = (float)(1 - _msPassed / _maxTime) + 0.1f;
            base.Draw(
                batch,
                destinationRectangle,
                sourceRectangle,
                color * fade);
        }

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

            _sfx.Play();
        }

        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
    }
}