using System.Linq;
using Igdc.Controls;
using Igdc.Drawables;

namespace Igdc.Scenes
{
    public partial class BattleScene
    {
        protected override void Update(SceneIterationArgument e)
        {
            _pressMark = false;
            for (var i = 0; i < _pressMatrix.GetUpperBound(0) + 1; i++)
                for (var j = 0; j < _pressMatrix.GetUpperBound(1) + 1; j++)
                    UpdatePress(e, i, j);
            
            foreach (var enemy in _enemies)
                UpdateEnemy(e, enemy);
            _enemies.RemoveAll(a => a.Health <= 0);
            
            foreach (var bullet in _bullets)
                UpdateBullet(e, bullet);
            _bullets.RemoveAll(a => a.DeleteMark);

            UpdatePlayer(e);

            if (!_enemies.Any())
                _winCallback?.Invoke();
        }

        private void UpdateEnemy(SceneIterationArgument e, BattleEnemy enemy)
        {
            // Shoot
            if (!_bullets.Any(b => b.Y == enemy.Y && b.Offset.Y < 40))
            {
                var maxrand = _bullets.Count == 0 ? 256 : _bullets.Count > _enemies.Count ? 1024 : 512;
                if (enemy.X == _player.X) maxrand -= 96;
                if (_player.Health >= 3) maxrand -= 96;
                if (_player.Health <= 1) maxrand += 96;
                if (e.Random.Next(0, maxrand) < enemy.ShootingChance)
                {
                    _bullets.Add(new BattleBullet { X = enemy.X, Y = enemy.Y, Color = Palette.Red1, Speed = 1 });
                }
            }
            // Check if hit
            if (_pressMatrix[enemy.X, enemy.Y])
            {
                e.Control.Feedback(null, 0.02f);
                _player.AnimateAttack();
                enemy.Health--;
                enemy.AnimateHit();
                var oldX = enemy.X;
                var oldY = enemy.Y;
                while (true)
                {
                    var newX = (byte)e.Random.Next(0, 3);
                    var newY = (byte)e.Random.Next(0, 2);
                    if (e.Random.Next(0, 2) == 1) newX = _player.X;
                    if (newX == oldX && newY == oldY) continue;
                    if (_enemies.Any(a => newX == a.X && newY == a.Y)) continue;
                    enemy.X = newX;
                    enemy.Y = newY;
                    break;
                }
            }
        }

        private void UpdateBullet(SceneIterationArgument e, BattleBullet bullet)
        {
            bullet.Offset.Y += bullet.Speed;
            var bulletY = 27 + 10 + 30 * bullet.Y + bullet.Offset.Y;
            if (bulletY > e.ScreenSize.Y + 10)
            {
                bullet.DeleteMark = true;
                return;
            }
            if (bullet.X == _player.X && bulletY >= 110 && bulletY <= 144)
            {
                e.Control.Feedback(1, null);
                _player.Health--;
                if (_player.Health <= 0) _loseCallback?.Invoke();
                bullet.DeleteMark = true;
            }
        }

        private void UpdatePlayer(SceneIterationArgument e)
        {
            if (_player.X > 0 && e.Control.BattleLeftButton.Pressed())
                _player.X--;
            if (_player.X < 2 && e.Control.BattleRightButton.Pressed())
                _player.X++;
        }

        private void UpdatePress(SceneIterationArgument e, int x, int y)
        {
            if (_pressMark)
            {
                _pressMatrix[x, y] = false;
            }
            else
            {
                var holding = e.Control.FieldCell[x, y].Holding();
                _pressMatrix[x, y] = holding;
                if (holding) _pressMark = true;
            }
        }
    }
}