using System;
using System.Linq;

namespace DALI.Toolkit.Utils
{
    /// <summary>
    /// Value name for a point
    /// </summary>
    public class NamePoint : IEquatable<NamePoint>
    {
        public char Letter { get; set; }
        public int Index { get; set; }
        public bool HavePrime { get; set; }

        public NamePoint()
        {
            Letter = '*';
            Index = 0;
            HavePrime = false;
        }

        public NamePoint(string name)
        {
            if (name.Length > 0)
            {
                Letter = name.First();

                char lastChar = name.Last();

                if (lastChar.ToString().Equals(ParamNamePoint.PrimeValue))
                {
                    HavePrime = true;
                }
                else
                {
                    HavePrime = false;
                }

                if (HavePrime)
                {
                    //Case A'
                    if (name.Length <= 2)
                    {
                        Index = 0;
                    }
                    //Cas A1'
                    else
                    {
                        string indexString = name.Substring(1, name.Length - 2);
                        Index = Int32.Parse(indexString);
                    }
                }
                else
                {
                    //Case A
                    if (name.Length <= 1)
                    {
                        Index = 0;
                    }
                    //Case A1
                    else
                    {
                        string indexString = name.Substring(1, name.Length - 1);
                        Index = Int32.Parse(indexString);
                    }
                }
            }
            else
            {
                throw new Exception("Error name empty for point");
            }
        }

        /// <summary>
        /// Allow to sorted => A A' B B'  A1 B1
        /// </summary>
        /// <param name="nametoCompate"></param>
        /// <returns></returns>
        public bool NameIsStrictUpTo(NamePoint nametoCompate)
        {
            if (this.Index > nametoCompate.Index)
            {
                return true;
            }
            else if (this.Index == nametoCompate.Index)
            {
                if (this.Letter != nametoCompate.Letter)
                {
                    if (this.Letter < nametoCompate.Letter)
                    {
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }
                else
                {
                    //A1 and A1'
                    if (this.HavePrime && !nametoCompate.HavePrime)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
            }
            else
            {
                return false;
            }
           
        }

        public NamePoint GetNextName()
        {
            char nextLetter = Letter;

            if(nextLetter == 'Z')
            {
                nextLetter = 'A';
                int nextIndex = Index + 1;

                string nextName = nextLetter.ToString() + nextIndex;

                return new NamePoint(nextName);
            }
            else
            {
                nextLetter++;

                string nextName = nextLetter.ToString() + Index;

                return new NamePoint(nextName);
            }
        }

        public override string ToString()
        {
            if(Index != 0)
            {
                if(HavePrime)
                {
                    return Letter.ToString() + Index + ParamNamePoint.PrimeValue;
                }
                else
                {
                    return Letter.ToString() + Index;
                }
            }
            else
            {
                if (HavePrime)
                {
                    return Letter.ToString() + ParamNamePoint.PrimeValue;
                }
                else
                {
                    return Letter.ToString();
                }
            }
        }

        public override int GetHashCode()
        {
            return Letter.GetHashCode() + Index.GetHashCode() + HavePrime.GetHashCode();
        }

        public bool Equals(NamePoint other)
        {
            if (this.Letter == other.Letter && this.Index == other.Index && this.HavePrime.Equals(other.HavePrime))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }
}
