using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CardGame
{
    /// <summary>
    /// カードの集合。
    /// Pileと違って順序を保たない。
    /// </summary>
    /// <remarks>
    /// 8バイト固定のビットアレイでカードの有無を記録。
    /// </remarks>
    public class CardSet : ICollection<Card>
    {
        public CardSet()
        {
        }

        public CardSet(IEnumerable<Card> cards)
            : this(Card.Serialize(cards))
        {
        }

        public CardSet(long bitArray)
        {
            this.bitArray = bitArray;
        }

        public long Serialize()
        {
            return this.bitArray;
        }

        long bitArray = 0L;

        #region IEnumerable<Card> メンバ

        public IEnumerator<Card> GetEnumerator()
        {
            for (int i = 0; i < 54; ++i)
            {
                bool bit = (this.bitArray & (1L << i)) != 0L;
                if (bit)
                    yield return new Card(i);
            }
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }

        #endregion
        #region ICollection<Card> メンバ

        public void Add(Card card)
        {
            this.bitArray |= 1L << card.ToInt();
        }

        public void Clear()
        {
            this.bitArray = 0L;
        }

        public bool Contains(Card item)
        {
            int i = item.ToInt();
            return (this.bitArray & (1L << i)) != 0L;
        }

        public void CopyTo(Card[] array, int arrayIndex)
        {
            int i = 0;

            foreach (var item in this)
            {
                if (i >= array.Length)
                    break;

                array[i] = item;
                ++i;
            }
        }

        public int Count
        {
            get
            {
                int count = 0;
                for (int i = 0; i < 54; ++i)
                {
                    bool bit = (this.bitArray & (1L << i)) != 0L;
                    if (bit)
                        ++count;
                }
                return count;
            }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public bool Remove(Card item)
        {
            if (this.Contains(item))
            {
                this.bitArray &= ~(1L << item.ToInt());

                return true;
            }
            return false;
        }

        #endregion
    }
}
