/// <summary>
        /// Move bullets to the direction given for the bullets
        /// </summary>
        private void MoveBullets()
        {
            foreach (var bullet in _bulletListModel.Bullets)
            {
                bullet.Position += bullet.Direction;
                var bulletArea = new Rectangle((int)bullet.Position.X, (int)bullet.Position.Y, 8, 8);

                if (!bullet.ShotByEnemy && bullet.Visible)
                {
                    foreach (var enemy in _enemyListModel.Enemies)
                    {
                        if (enemy.Area.Intersects(bulletArea) && !enemy.IsDead)
                        {
                            bullet.Visible = false;
                            enemy.HPLeft  -= bullet.BulletDamage;
                            if (enemy.HPLeft <= 0)
                            {
                                _enemyDies.Play(0.3f, 1f, 0f);
                                enemy.IsDead = true;
                                _playerModel.AddXp(enemy.IsBoss ? 50 : (1 + _playerModel.Level));
                            }
                        }
                    }
                }

                if (bullet.ShotByEnemy && bullet.Visible)
                {
                    var playerArea = new Rectangle((int)_playerModel.Position.X + 4, (int)_playerModel.Position.Y + 4, 56, 56);

                    if (bulletArea.Intersects(playerArea) && !_playerModel.Invulnerable)
                    {
                        bullet.Visible       = false;
                        _playerModel.HPLeft -= bullet.BulletDamage;

                        if (_playerModel.HPLeft <= 0)
                        {
                            _playerDies.Play(0.3f, 1f, 0f);
                            _reset.Reset(ResetMode.Death);
                        }
                    }
                }

                if (bullet.Position.Y < 0 ||
                    bullet.Position.Y >= VirtualScreenSize.Height * VirtualScreenSize.ScreenSizeMultiplier ||
                    bullet.Position.X < 0 ||
                    bullet.Position.X >= VirtualScreenSize.Width * VirtualScreenSize.ScreenSizeMultiplier)
                {
                    bullet.Visible = false;
                }
            }
        }
        /// <summary>
        /// Moves generated bonus items.
        /// </summary>
        /// <param name="gameTime"></param>
        private void MoveItems(GameTime gameTime)
        {
            var playerArea = new Rectangle((int)_playerModel.Position.X + 4, (int)_playerModel.Position.Y + 4, 56, 56);

            foreach (var item in _bonusItemListModel.BonusItems)
            {
                if (item.Area.Intersects(playerArea) && !item.PickedUpByPlayer)
                {
                    switch (item.Type)
                    {
                    case BonusItemType.XP:
                        _playerModel.AddXp((int)item.Amount * _playerModel.Level);
                        item.PickedUpByPlayer = true;
                        item.ShowText         = true;
                        break;

                    case BonusItemType.HP:
                        _playerModel.HP      += item.Amount;
                        item.PickedUpByPlayer = true;
                        item.ShowText         = true;
                        break;

                    case BonusItemType.Damage:
                        _playerModel.Damage  += item.Amount;
                        item.PickedUpByPlayer = true;
                        item.ShowText         = true;
                        break;

                    case BonusItemType.ExtraLive:
                        if (_playerModel.Lives < 5)
                        {
                            _playerModel.Lives += (int)item.Amount;
                        }
                        else
                        {
                            _playerModel.HP              += 0.1f;
                            _playerModel.HPLeft          += 0.1f;
                            _playerModel.HPStartingValue += 0.1f;
                        }
                        item.PickedUpByPlayer = true;
                        item.ShowText         = true;
                        break;

                    case BonusItemType.Speed:
                        _playerModel.Speed   += item.Amount;
                        item.PickedUpByPlayer = true;
                        item.ShowText         = true;
                        break;

                    case BonusItemType.Bullet:
                        if (_playerModel.BulletAmount < 12)
                        {
                            _playerModel.BulletAmount += item.Amount;
                        }
                        else
                        {
                            _playerModel.Damage += 0.1f;
                            _playerModel.DamageStartingValue += 0.1f;
                        }
                        item.PickedUpByPlayer = true;
                        item.ShowText         = true;
                        break;
                    }
                    _soundEffect.Play(0.3f, 1f, 0f);
                }

                // Check if item is either at the target position or close to it
                // Randomize new target position if true
                var targetArea = new Rectangle((int)item.TargetPosition.X, (int)item.TargetPosition.Y, 8, 8);

                if (item.Area.Intersects(targetArea) && !item.PickedUpByPlayer)
                {
                    Random random = new Random();
                    var    x      = random.Next(VirtualScreenSize.Width * VirtualScreenSize.ScreenSizeMultiplier - 100);
                    var    y      = random.Next(VirtualScreenSize.Height * VirtualScreenSize.ScreenSizeMultiplier);
                    item.TargetPosition = new Vector2(x, y);
                }
                else
                {
                    Move(item, _distance + _playerModel.Speed, 30, 30);
                }
            }

            HideItemTexts(gameTime);
        }
        public override void Enter(params object[] args)
        {
            _screen      = new RenderTarget2D(StateMachine.Game.GraphicsDevice, VirtualScreenSize.Width * VirtualScreenSize.ScreenSizeMultiplier, VirtualScreenSize.Height * VirtualScreenSize.ScreenSizeMultiplier);
            _spriteBatch = new SpriteBatch(StateMachine.Game.GraphicsDevice);

            if (MediaPlayer.State != MediaState.Playing)
            {
                MediaPlayer.Play(_levelMusic);
                MediaPlayer.IsRepeating = true;
                MediaPlayer.Volume      = 0.2f;
            }

            bool resetForNewGame = true;

            if (args.Length > 0 && args[0] is bool)
            {
                resetForNewGame = (bool)args[0];
            }

            if (resetForNewGame)
            {
                int highScore = 0;
                using (var connection = new SQLiteConnection("Data Source=genericspaceshooter.db"))
                {
                    connection.Open();
                    var command = new SQLiteCommand(connection)
                    {
                        CommandText = "SELECT Stage FROM HighScore ORDER BY Stage DESC LIMIT 1"
                    };
                    SQLiteDataReader reader = command.ExecuteReader();

                    while (reader.Read())
                    {
                        highScore = reader.GetInt32(0);
                    }
                    connection.Close();
                }

                _playerModel = new PlayerModel(1, highScore);
            }
            else
            {
                _playerModel        = _playerService.GetPlayer();
                _playerModel.Stage += 1;
                _playerModel.Lives  = _playerModel.Stage % 4 == 0 ? _playerModel.Lives++ : _playerModel.Lives;
                _playerModel.AddXp(50);
                _playerModel.ResetPosition(ResetMode.Level);
                if (_playerModel.Stage > _playerModel.HighScore)
                {
                    _playerModel.HighScore = _playerModel.Stage;
                }
            }

            _playerService.SetPlayer(_playerModel);

            // Create models
            _bulletListModel    = new BulletListModel(new List <BulletModel>());
            _enemyListModel     = new EnemyListModel(EnemyFactory.CreateStage(_playerModel.Stage));
            _bonusItemListModel = new BonusItemListModel(BonusItemFactory.CreateBonusItemsForStage(_playerModel.Stage));

            // Create and add controllers
            var playerController     = new PlayerController(_playerModel);
            var enemyController      = new EnemyController(_enemyListModel, _playerModel, playerController, StateMachine.Game.Content);
            var bulletListController = new BulletController(_bulletListModel, _playerModel, _enemyListModel, playerController, StateMachine.Game.Content);
            var bonusItemController  = new BonusItemController(_bonusItemListModel, _playerModel, StateMachine.Game.Content);

            _controllers.Add(playerController);
            _controllers.Add(enemyController);
            _controllers.Add(bulletListController);
            _controllers.Add(bonusItemController);

            // Add views
            _views.Add(new PlayerView(StateMachine.Game.Content, _spriteBatch, _playerModel));
            _views.Add(new BulletView(StateMachine.Game.Content, _spriteBatch, _bulletListModel));
            _views.Add(new EnemyView(StateMachine.Game.Content, _spriteBatch, _enemyListModel));
            _views.Add(new StatsView(StateMachine.Game.Content, _spriteBatch, _playerModel, _enemyListModel));
            _views.Add(new BonusItemView(StateMachine.Game.Content, _spriteBatch, _bonusItemListModel));
        }