using System;
using Igdc.Controls;
using Igdc.Drawables;
using Igdc.Extensions;
using Microsoft.Xna.Framework;
using System.Linq;

namespace Igdc.Scenes
{
    public partial class MapScene
    {
        private bool _firstUpdate = true;

        protected override void Update(SceneIterationArgument e)
        {
            foreach (var enemy in _enemies)
                UpdateEnemy(e, enemy);
            foreach (var ally in _allies)
                UpdateAlly(e, ally);
            _enemies.RemoveAll(a => a.DeleteMark);
            UpdatePlayer(e);
            UpdateCamera(e);
            _firstUpdate = false;
            if (!_enemies.Any())
                IgdcGame.Current.Navigate<StoryScene>(new StoryPackage
                {
                    StoryLink = "Конец",
                    Callback = () => IgdcGame.Current.Load()
                });
        }

        private void UpdateEnemy(SceneIterationArgument e, MapEnemy enemy)
        {
            if (enemy.DeleteMark) return;
            if (enemy.IsNear(_player))
                IgdcGame.Current.Navigate<BattleScene>(new BattlePackage
                {
                    Background = _package.Background,
                    Player = new BattlePlayer { Health = 3 },
                    Enemies = enemy.CreateBattleEnemies(),
                    WinCallback = () =>
                    {
                        enemy.DeleteMark = true;
                        IgdcGame.Current.NavigateBack();
                    },
                    LoseCallback = () => IgdcGame.Current.Navigate<MenuScene>(null)
                });
        }

        private void UpdateAlly(SceneIterationArgument e, MapAlly ally)
        {
            if (ally.IsNear(_player))
                IgdcGame.Current.Navigate<StoryScene>(new StoryPackage
                {
                    StoryLink = ally.Story,
                    Callback = () =>
                    {
                        ally.CanPlay = false;
                        IgdcGame.Current.NavigateBack();
                    }
                });
        }

        private void UpdatePlayer(SceneIterationArgument e)
        {
            if (e.Control.MoveUpButton.Pressed())
            {
                var hasMovement = false;
                if (_player.Y > 0
                     && _map[_player.X, _player.Y - 1].X < 1)
                {
                    hasMovement = true;
                    _player.Y--;
                }
                _player.AnimateUp(hasMovement);
            }
            if (e.Control.MoveRightButton.Pressed())
            {
                var hasMovement = false;
                if (_player.X < _map.GetUpperBound(0) - 0
                     && _map[_player.X + 1, _player.Y].X < 1)
                {
                    hasMovement = true;
                    _player.X++;
                }
                _player.AnimateRight(hasMovement);
            }
            if (e.Control.MoveDownButton.Pressed())
            {
                var hasMovement = false;
                if (_player.Y < _map.GetUpperBound(1) - 0
                     && _map[_player.X, _player.Y + 1].X < 1)
                {
                    hasMovement = true;
                    _player.Y++;
                }
                _player.AnimateDown(hasMovement);
            }
            if (e.Control.MoveLeftButton.Pressed())
            {
                var hasMovement = false;
                if (_player.X > 0
                     && _map[_player.X - 1, _player.Y].X < 1)
                {
                    hasMovement = true;
                    _player.X--;
                }
                _player.AnimateLeft(hasMovement);
            }
        }

        private void UpdateCamera(SceneIterationArgument e)
        {
            var playerX = _player.X * _player.Size.X + (_player.Size.X / 2);
            var screenCenterX = e.ScreenSize.X / 2;
            var maxTargetX = _map.GetUpperBound(0) * 16 - e.ScreenSize.X + 16;
            var targetX = playerX - screenCenterX;
            if (targetX < 0) targetX = 0;
            if (targetX > maxTargetX) targetX = maxTargetX;

            var playerY = _player.Y * _player.Size.Y + (_player.Size.Y / 2);
            var screenCenterY = e.ScreenSize.Y / 2;
            var maxTargetY = _map.GetUpperBound(0) * 16 - e.ScreenSize.Y + 16;
            var targetY = playerY - screenCenterY;
            if (targetY < 0) targetY = 0;
            if (targetY > maxTargetY) targetY = maxTargetY;

            var oldCamera = Camera;
            Camera = Camera.Interpolate(new Point(targetX, targetY), _firstUpdate);
        }
    }
}