using ActionGame.GameArtifacts.Models.Characters;
using ActionGame.GameArtifacts.Models.Game;
using ActionGame.GameArtifacts.Operators.Characters;
using ActionGame.GameResources.Models;
using ActionGame.RawResources.Manager;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;


namespace ActionGame.GameArtifacts.Models.WeaponSprites
{
    public class Explosion : IWeaponSprite
    {
        public WorldPosition WorldPosition { get; set; }
        public MovementPhysics MovementPhysics { get; set; }
        public Boolean IsExpired { get; set; }

        private IRawContentManager rawContentManager;
        private GameData gameData;
        private Int32 attack;
        private Boolean hasDamaged;

        private IList<Texture2D> textures;
        private Int32 frame;
        private TimeSpan lastFrameUpdateTime;


        private TimeSpan creationTime;
        private Int32 size;
        private IList<IBattleObject> ignoredObjects;


        public Explosion(IRawContentManager rawContentManager, GameData gameData, WorldPosition worldPosition, Int32 attack, Int32 size, IList<IBattleObject> ignoredObjects)
        {
            IsExpired = false;
            this.rawContentManager = rawContentManager;
            this.gameData = gameData;
            this.WorldPosition = worldPosition.Copy();
            this.attack = attack;
            this.MovementPhysics = new MovementPhysics();

            this.textures = new List<Texture2D>();
            this.textures.Add(rawContentManager.TextureRepository.GetContent(@"textures\items\explosion-sprite-1"));
            this.textures.Add(rawContentManager.TextureRepository.GetContent(@"textures\items\explosion-sprite-2"));
            this.textures.Add(rawContentManager.TextureRepository.GetContent(@"textures\items\explosion-sprite-3"));
            this.textures.Add(rawContentManager.TextureRepository.GetContent(@"textures\items\explosion-sprite-4"));

            this.size = size;

            frame = 0;
            hasDamaged = false;

            this.ignoredObjects = ignoredObjects;
            if (this.ignoredObjects == null) this.ignoredObjects = new List<IBattleObject>();
        }


        public Rectangle GetCurrentCollisionArea()
        {
            Rectangle rect = GetCollisionAreaAtPosition(this.WorldPosition.PositionX, this.WorldPosition.PositionY);

            return rect;
        }


        public Rectangle GetCollisionAreaAtPosition(int x, int y)
        {
            Rectangle rect = new Rectangle(x, y - size, size, size);

            return rect;
        }


        public Rectangle GetDrawArea()
        {
            return GetCurrentCollisionArea();
        }


        public void Update(GameTime gameTime)
        {
            if (creationTime == default(TimeSpan)) creationTime = gameTime.TotalGameTime;
            if (lastFrameUpdateTime == default(TimeSpan)) lastFrameUpdateTime = gameTime.TotalGameTime;

            //frame update
            if ((gameTime.TotalGameTime - lastFrameUpdateTime).TotalSeconds > 0.125)
            {
                lastFrameUpdateTime = gameTime.TotalGameTime;

                frame++;
                if (frame >= this.textures.Count) frame = 0;
            }

            if (hasDamaged == false)
            {
                DetectHitAndDoDamage();
            }

            //expire
            if ((gameTime.TotalGameTime - creationTime).TotalSeconds > 0.5)
            {
                IsExpired = true;
            }
        }


        private void DetectHitAndDoDamage()
        {
            IList<IBattleObject> objectsInRange = gameData.GameState.GetBattleObjectsInArea(GetCurrentCollisionArea());

            foreach(IBattleObject target in objectsInRange)
            {
                if (ignoredObjects.Contains(target) == false)
                {
                    Damager damager = new Damager();

                    Int32 damageDone = damager.Do(attack, target);

                    if (damageDone != 0)
                    {
                        DamageSprite damageSprite = new DamageSprite(rawContentManager, target, damageDone, target.WorldPosition);
                        gameData.GameState.ActiveDisplaySprites.Add(damageSprite);
                    }

                    hasDamaged = true;
                }
            }
        }


        public void Draw(SpriteBatch spriteBatch)
        {
            Rectangle rect = this.GetDrawArea();

            spriteBatch.Draw(this.textures[frame], rect, Color.White);
        }


    }
}
