using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;

namespace QwirkleClassLibrary.Tiles
{
    [DataContract]
    public class TileBag
    {
        [DataMember]
        private readonly List<Tile> tiles = [];

        public ReadOnlyCollection<Tile>? TilesBag { get; private set; }


        /// <summary>
        /// This is the constructor for the TileBag. It will create a tile of each of the possibilities among the Color and Shape Enums.
        /// </summary>
        /// <param name="nbSet">This parameter is used to indicate the number of copies we want to create.</param>
        /// <exception cref="ArgumentException">Throw an exception if the number of copies is negative (impossible) or superior to 3 (contradiction with the rules).</exception>
        public TileBag(int nbSet)
        {
            if (nbSet < 0 || nbSet > 3)
            {
                throw new ArgumentException(nbSet.ToString());
            }

            for (int i = 0; i < nbSet; i++)
            {
                foreach (Shape s in Enum.GetValues(typeof(Shape)))
                {
                    foreach (Color c in Enum.GetValues(typeof(Color)))
                    {
                        Tile t = new(s, c);
                        tiles.Add(t);
                    }
                }
            }

            Init();
        }

        /// <summary>
        /// This method is used to add a tile in the tile bag.
        /// </summary>
        /// <param name="tile">The tile we want to add in the bag.</param>
        public void AddTileInBag(Tile tile)
        {
            tiles.Add(tile);
        }

        /// <summary>
        /// Remove a tile in the tile bag.
        /// </summary>
        /// <param name="tile">The tile you want to remove from the bag.</param>
        /// <returns>True if the remove was successfull, false if it failed.</returns>
        public bool RemoveTileInBag(Tile tile)
        {
            for (int i = 0; i < tiles.Count; i++)
            {
                if (tiles[i] == tile)
                {
                    tiles.RemoveAt(i);
                    return true;
                }
            }
            return false;
        }

        [OnDeserialized]
        private void Init(StreamingContext sc = new())
        {
            TilesBag = tiles.AsReadOnly();
        }
    }
}