using System.Collections.Generic;
using System.Linq;
using Trivia.Infra;

namespace Trivia.Master
{
    public class Game_Master
    {
        private readonly bool[] _inPenaltyBox = new bool[6];

        private readonly int[] _places = new int[6];

        private readonly List<string> _players = new List<string>();

        private readonly LinkedList<string> _popQuestions = new LinkedList<string>();

        private readonly int[] _purses = new int[6];

        private readonly LinkedList<string> _rockQuestions = new LinkedList<string>();

        private readonly LinkedList<string> _scienceQuestions = new LinkedList<string>();

        private readonly LinkedList<string> _sportsQuestions = new LinkedList<string>();

        private int _currentPlayer;

        private bool _isGettingOutOfPenaltyBox;

        private IPrint _print;

        public Game_Master(IPrint print, int pointsToWin)
        {
            PointsToWin = pointsToWin;
            _print = print;
            for (var i = 0; i < 50; i++)
            {
                _popQuestions.AddLast("Pop Question " + i);
                _scienceQuestions.AddLast("Science Question " + i);
                _sportsQuestions.AddLast("Sports Question " + i);
                _rockQuestions.AddLast(CreateRockQuestion(i));
            }
        }

        public int PointsToWin { get; }

        public bool Add(string playerName)
        {
            _players.Add(playerName);
            _places[HowManyPlayers()] = 0;
            _purses[HowManyPlayers()] = 0;
            _inPenaltyBox[HowManyPlayers()] = false;

            _print.WriteLine(playerName + " was added");
            _print.WriteLine("They are player number " + _players.Count);
            return true;
        }

        public string CreateRockQuestion(int index)
        {
            return "Rock Question " + index;
        }

        public int HowManyPlayers()
        {
            return _players.Count;
        }

        public bool IsPlayable()
        {
            return HowManyPlayers() >= 2;
        }

        public void Roll(int roll)
        {
            _print.WriteLine(_players[_currentPlayer] + " is the current player");
            _print.WriteLine("They have rolled a " + roll);

            if (_inPenaltyBox[_currentPlayer])
            {
                if (roll % 2 != 0)
                {
                    _isGettingOutOfPenaltyBox = true;

                    _print.WriteLine(_players[_currentPlayer] + " is getting out of the penalty box");
                    _places[_currentPlayer] = _places[_currentPlayer] + roll;
                    if (_places[_currentPlayer] > 11) _places[_currentPlayer] = _places[_currentPlayer] - 12;

                    _print.WriteLine(_players[_currentPlayer]
                            + "'s new location is "
                            + _places[_currentPlayer]);
                    _print.WriteLine("The category is " + CurrentCategory());
                    AskQuestion();
                }
                else
                {
                    _print.WriteLine(_players[_currentPlayer] + " is not getting out of the penalty box");
                    _isGettingOutOfPenaltyBox = false;
                }
            }
            else
            {
                _places[_currentPlayer] = _places[_currentPlayer] + roll;
                if (_places[_currentPlayer] > 11) _places[_currentPlayer] = _places[_currentPlayer] - 12;

                _print.WriteLine(_players[_currentPlayer]
                        + "'s new location is "
                        + _places[_currentPlayer]);
                _print.WriteLine("The category is " + CurrentCategory());
                AskQuestion();
            }
        }

        public bool WasCorrectlyAnswered()
        {
            if (_inPenaltyBox[_currentPlayer])
            {
                if (_isGettingOutOfPenaltyBox)
                {
                    _print.WriteLine("Answer was correct!!!!");
                    _purses[_currentPlayer]++;
                    _print.WriteLine(_players[_currentPlayer]
                            + " now has "
                            + _purses[_currentPlayer]
                            + " Gold Coins.");

                    var winner = DidPlayerWin();
                    _currentPlayer++;
                    if (_currentPlayer == _players.Count) _currentPlayer = 0;

                    return winner;
                }
                else
                {
                    _currentPlayer++;
                    if (_currentPlayer == _players.Count) _currentPlayer = 0;
                    return true;
                }
            }
            else
            {
                _print.WriteLine("Answer was corrent!!!!");
                _purses[_currentPlayer]++;
                _print.WriteLine(_players[_currentPlayer]
                        + " now has "
                        + _purses[_currentPlayer]
                        + " Gold Coins.");

                var winner = DidPlayerWin();
                _currentPlayer++;
                if (_currentPlayer == _players.Count) _currentPlayer = 0;

                return winner;
            }
        }

        public bool WrongAnswer()
        {
            _print.WriteLine("Question was incorrectly answered");
            _print.WriteLine(_players[_currentPlayer] + " was sent to the penalty box");
            _inPenaltyBox[_currentPlayer] = true;

            _currentPlayer++;
            if (_currentPlayer == _players.Count) _currentPlayer = 0;
            return true;
        }

        private void AskQuestion()
        {
            if (CurrentCategory() == "Pop")
            {
                _print.WriteLine(_popQuestions.First());
                _popQuestions.RemoveFirst();
            }
            if (CurrentCategory() == "Science")
            {
                _print.WriteLine(_scienceQuestions.First());
                _scienceQuestions.RemoveFirst();
            }
            if (CurrentCategory() == "Sports")
            {
                _print.WriteLine(_sportsQuestions.First());
                _sportsQuestions.RemoveFirst();
            }
            if (CurrentCategory() == "Rock")
            {
                _print.WriteLine(_rockQuestions.First());
                _rockQuestions.RemoveFirst();
            }
        }

        private string CurrentCategory()
        {
            if (_places[_currentPlayer] == 0) return "Pop";
            if (_places[_currentPlayer] == 4) return "Pop";
            if (_places[_currentPlayer] == 8) return "Pop";
            if (_places[_currentPlayer] == 1) return "Science";
            if (_places[_currentPlayer] == 5) return "Science";
            if (_places[_currentPlayer] == 9) return "Science";
            if (_places[_currentPlayer] == 2) return "Sports";
            if (_places[_currentPlayer] == 6) return "Sports";
            if (_places[_currentPlayer] == 10) return "Sports";
            return "Rock";
        }

        private bool DidPlayerWin()
        {
            return !(_purses[_currentPlayer] == PointsToWin);
        }
    }
}