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

namespace shuchancontrol
{
    /// <summary>
    /// 駒の位置を表すクラス。
    /// </summary>
    public class ShuchanPiecePosition : ICloneable, IComparable
    {
        /// <summary>
        /// 1つの数値で座標を表す。ランク(ランク1=0)*8+ファイル(a=0)/負の値:無効位置(駒捨て場)/ランク9としてA-Hの予備駒を指す
        /// </summary>
        public int Position { get; set; }

        /// <summary>
        /// 予備駒を示すランク。
        /// </summary>
        public const int ExtraPieceRank = 8;

        /// <summary>
        /// チェスのルール上のランクを取得する。(ランク1=数値0)
        /// </summary>
        public int Rank
        {
            get
            {
                if (Position < 0)
                {
                    return 0;
                }

                return Position / 8;
            }
            set
            {
                Position = value * 8 + File;
            }
        }

        /// <summary>
        /// チェスのルール上のファイルを取得する。(ファイルA=数値0)Positionが負のときの値は不定。
        /// </summary>
        public int File
        {
            get
            {
                return Position % 8;
            }
            set
            {
                Position = Rank * 8 + value;
            }
        }

        /// <summary>
        /// チェスのルールに定義された位置(ランク1-8)かどうかを返す。
        /// </summary>
        public bool IsRuralPosition
        {
            get
            {
                bool result = false;
                if (Rank >= 0 & Rank <= 7)
                {
                    result = true;
                }
                return result;
            }
        }

        public override string ToString()
        {
            string posstr = "";
            posstr += (char)('a' + File);
            posstr += (Rank + 1).ToString();
            return posstr;
        }

        public ShuchanPiecePosition()
            : this(-1)
        {
        }

        public ShuchanPiecePosition(int position)
        {
            this.Position = position;
        }

        public ShuchanPiecePosition(int rank, int file)
        {
            this.Rank = rank;
            this.File = file;
        }

        public ShuchanPiecePosition(string pos)
        {
            if (pos == null)
            {
                throw new ArgumentNullException();
            }

            pos = pos.Trim();
            if (pos.Length != 2)
            {
                throw new ArgumentException();
            }

            int rank, file;
            if (!int.TryParse(pos.Substring(1, 1), out rank))
            {
                throw new ArgumentException();
            }
            rank--; //ルール上のランクは1-8だが内部表現では0-7なので変換
            if ((rank < 0) | (rank > 7))
            {
                throw new ArgumentOutOfRangeException();
            }

            file = (int)(pos.ToLower()[0] - 'a');
            if ((file < 0) | (file > 7))
            {
                throw new ArgumentOutOfRangeException();
            }

            this.Rank = rank;
            this.File = file;
        }

        #region ICloneable メンバ

        public object Clone()
        {
            return new ShuchanPiecePosition(this.Position);
        }

        #endregion

        #region IComparable メンバ

        public int CompareTo(object obj)
        {
            ShuchanPiecePosition target = obj as ShuchanPiecePosition;
            if (target == null)
            {
                return 1;
            }

            return this.Position - target.Position;
        }

        #endregion
    }
}
