using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine.SceneManagement;
using UnityEngine;

namespace Assets._game.scripts
{
    public class GameManager : Singleton<GameManager>
    {
        public Game GameInstance { get; private set; }

        public PlayArea PlayArea { get; set; }

        public GameObject FighterPrefab;

        public ProjectileData DefaultProjectile; //TODO: Remove

        public List<GameData> Games;

        public GameStatistics Stats;

        public void NewGame(GameData game)
        {
            GameInstance = new Game(game);

            GameInstance.GameOver += OnGameOver;
            if (PlayArea)
            {
                PlayArea.SetSize(game.GameRadius);
            }
        }

        private void OnGameOver(Player winner)
        {
            if (winner != null)
            {
                Debug.LogFormat("Game over. Winner is {0}", winner.Controller.Name);
            }
            Stats.OnGameOver(winner);

            StartCoroutine(WaitForEnd());
        }

        private IEnumerator WaitForEnd()
        {
            //TODO: Celebrate?
            yield return new WaitForSeconds(5);
            LoadScene("endScreen");
        }

        public bool HasPlayer(int playerId)
        {
            return GameInstance.Players.Any(x => x.PlayerId == playerId);
        }

        public Player AddPlayer(PlayerData data, int playerId = -1)
        {
            if (GameInstance == null)
            {
                Debug.LogError("No game");
                return null;
            }

            var player = GameInstance.AddPlayer(data, playerId);
            player.PlayerHit += OnPlayerHit;

            return player;
        }

        private void OnPlayerHit(Player player1, int amount, GameEntity source)
        {

        }

        public bool RemovePlayer(Player player)
        {
            if (GameInstance == null)
            {
                Debug.LogError("No game");
                return false;
            }

            player.PlayerHit -= OnPlayerHit;

            return GameInstance.RemovePlayer(player);
        }

        public void GoToMenu()
        {
            LoadScene("menu");
        }

        public void StartGame()
        {
            if (GameInstance == null)
            {
                Debug.LogWarning("No game created");
                //TODO: Setup default
            }

            Stats = new GameStatistics(GameInstance);

            Debug.Log("Starting game");

            StartCoroutine(StartGameRoutine());
        }

        public IEnumerator StartGameRoutine()
        {
            var asyncOperation = SceneManager.LoadSceneAsync("game");
            while (!asyncOperation.isDone)
            {
                yield return null;
            }
            yield return null;
            CameraManager.Instance.CreateGameCameraRig();
            Debug.Log("Soon there. 2 seconds");
            yield return new WaitForSeconds(2f);
            GameInstance.Start();
            int index = 0;
            float step = 360f / GameInstance.Players.Count;
            foreach (var player in GameInstance.Players)
            {
                Debug.Log("Creating player from data");

                var spawnPoint = PlayArea.GetSpawnPoint(Vector3.up * 100f, GameInstance.Data.GameRadius, index++ * step);
                var rotation = Quaternion.LookRotation(Vector3.zero - spawnPoint).eulerAngles;
                rotation.x = 0;
                rotation.z = 0;
                var goPlayer = Instantiate(FighterPrefab, spawnPoint, Quaternion.Euler(rotation));
                //var goPlayer = Instantiate(FighterPrefab, Vector3.up * 100f, Quaternion.Euler(0, UnityEngine.Random.Range(0, 360), 0));
                goPlayer.name = string.Format("{0} - {1}", player.Data.Name, player.PlayerId);
                //rigidBody.constraints = RigidbodyConstraints.FreezeRotation;
                var model = Instantiate(player.Data.Model);
                model.transform.parent = goPlayer.transform;
                model.transform.localPosition = Vector3.zero;
                model.transform.localRotation = Quaternion.Euler(-90f, 0f, 0f);
                PlayerController controller = goPlayer.AddComponent<PlayerController>();
                controller.Init(player, model.GetComponent<Collider>());
                player.Controller = controller;
                CameraManager.Instance.AddTarget(goPlayer.transform);
                //TODO: Spawn in random positionvvvvvvv
                yield return null;
            }

        }

        private void LoadScene(string name)
        {
            //TODO: Make async and route through loading scene
            SceneManager.LoadScene(name);
        }

        public static Color GetPlayerColor(int playerId, float alpha)
        {
            var color = Color.white;
            switch (playerId)
            {
                case 0:
                    {
                        color = new Color(0f, 0.89f, 1f, alpha); // Blue
                        break;
                    }
                case 1:
                    {
                        color = new Color(1f, 0.77f, 0f, alpha); // Yellow
                        break;
                    }
                case 2:
                    {
                        color = new Color(1f, 0f, 0.33f, alpha); // Red
                        break;
                    }
                case 3:
                    {
                        color = new Color(0.75f, 1f, 0, alpha); // Green
                        break;
                    }
            }
            return color;
        }
    }
}
