using Models.Game;

namespace Models.Interfaces
{

    /// <summary>
    /// Interface for the rules of the game.
    /// </summary>
    public interface IRules
    {
        //public bool NearCellIsValid(Position playerChoicePosition, SortedDictionary<Position, Cell> cells);

        /// <summary>
        /// Return true if the cell is empty, otherwise false.
        /// </summary>
        /// <param name="playerChoice">The cell that the player chose</param>
        /// <returns> Return true if the cell is empty, otherwise false.</returns>
        public bool IsCellEmpty(Cell playerChoice);

        /// <summary>
        /// Check if the cell is valid.
        /// </summary>
        /// <param name="playerChoicePosition">The cell that the player chose</param>
        /// <param name="cells">Boards of the actual game</param>
        /// <returns>true if the cell is valid; otherwise, false</returns>
        public bool IsCellValid(Cell playerChoicePosition, List<Cell> cells);

        //public bool IsRopePath(Cell playerChoice, HashSet<RopePath> ropePaths);

        //public bool IsAdjacent(Cell cell1, Cell cell2, List<Position, Cell> cells);

        //public int HowMany(Cell playerChoice, List<Position, Cell> cells);

        //public void SetValueAndPenalty(int valueChoice, Cell playerChoice, List<Position, Cell> cells);


        /// <summary>
        /// Check if the given cell is adjacent to the target cell.
        /// </summary>
        /// <param name="choosenCell">The chosen cell.</param>
        /// <param name="targetCell">The target cell.</param>
        /// <returns>True if the given cell is adjacent to the target cell; otherwise false.</returns>
        public bool IsCellAdjacent(Cell choosenCell, Cell targetCell);

        /// <summary>
        /// Check if the given cell can be played there.
        /// If there isn't any adjacent cell with a value, or if the cell is null, it returns false.
        /// </summary>
        /// <param name="choosenCell">The chosen cell.</param>
        /// <param name="cells">The list of cells.</param>
        /// <returns>True if the chosen cell can be played here; otherwise false.</returns>
        public bool NearCellIsValid(Cell choosenCell, List<Cell> cells);

        /// <summary>
        /// Check if the chosen cell is valid and add it to the matching zone.
        /// If there is a nearby cell with matching value but no zone already created, it creates one
        /// </summary>
        /// <param name="chosenCell">The chosen cell.</param>
        /// <param name="map">The map.</param>
        /// <returns></returns>
        public void IsZoneValidAndAddToZones(Cell chosenCell, Map map);

        /// <summary>
        /// Check if the value of the chosen cell is in the zones of the player.
        /// </summary>
        /// <param name="chosenCell">The cell chosen by the player.</param>
        /// <param name="zones">The list of the player's zones.</param>
        /// <returns>True if the value is in the zones; otherwise false.</returns>
        public bool IsValueInZones(Cell chosenCell, List<List<Cell>> zones);

        /// <summary>
        /// Check if the chosen cell is in any of the player's zones.
        /// </summary>
        /// <param name="chosenCell">The chosen cell.</param>
        /// <param name="zones">The list of the player's zones.</param>
        /// <returns>True if the cell is in any of the zones; otherwise false.</returns>
        public bool IsCellInZone(Cell chosenCell, List<List<Cell>> zones);

        /// <summary>
        /// Add the chosen cell to the list of zones.
        /// The zone must be created before.
        /// </summary>
        /// <param name="chosenCell">The chosen cell.</param>
        /// <param name="zones">The list of zones.</param>
        public void AddToZone(Cell chosenCell, List<List<Cell>> zones);

        /// <summary>
        /// Create a new zone with the two cells and add it to the map.
        /// </summary>
        /// <param name="firstCell">The first cell.</param>
        /// <param name="secondCell">The second cell.</param>
        /// <param name="map">The map.</param>
        public void NewZoneIsCreated(Cell firstCell, Cell secondCell, Map map);

        /// <summary>
        /// Get every adjacent cell of the chosen cell.
        /// </summary>
        /// <param name="choosenCell">The chosen cell.</param>
        /// <param name="cells">The list of cells.</param>
        /// <returns>The list of adjacent cells.</returns>
        public List<Cell> EveryAdjacentCells(Cell choosenCell, List<Cell> cells);

        /// <summary>
        /// Calculate the final score by summing up the values of all the zones.
        /// </summary>
        /// <param name="zones">The list of zones.</param>
        /// <returns>The final score.</returns>
        public int? FinalCalculusOfZones(List<List<Cell>> zones);

        /// <summary>
        /// Check if the adjacent cell is in any of the rope paths.
        /// </summary>
        /// <param name="adjacente">The adjacent cell.</param>
        /// <param name="ropePaths">The list of rope paths.</param>
        /// <param name="index">The index of the rope path.</param>
        /// <returns>True if the adjacent cell is in the rope path; otherwise false.</returns>
        public bool IsInRopePaths(Cell adjacente, List<List<Cell>> ropePaths, int index);

        /// <summary>
        /// Check if the chosen cell has the same value as the rope path at the given index.
        /// </summary>
        /// <param name="choosenCell">The chosen cell.</param>
        /// <param name="ropePaths">The list of rope paths.</param>
        /// <param name="index">The index of the rope path.</param>
        /// <returns>True if the chosen cell has the same value as the rope path; otherwise false.</returns>
        public bool AsValue(Cell choosenCell, List<List<Cell>> ropePaths, int index);
    }
}