using System;
using System.Text;

namespace Quik.Typography
{
    public static class UnicodeUtil
    {

        public static bool IsWhiteSpace(int chr)
        {
            switch (chr)
            {
            case '\t': case '\n': case '\v': case '\f': case '\r': case ' ':
            case '\u0085': case '\u00A0': case '\u1680': case '\u2000':
            case '\u2001': case '\u2002': case '\u2003': case '\u2004':
            case '\u2005': case '\u2006': case '\u2007': case '\u2008':
            case '\u2009': case '\u200A': case '\u2028': case '\u2029':
            case '\u202F': case '\u205F': case '\u3000': case '\u180E':
            case '\u200B': case '\u200C': case '\u200D': case '\u2060':
                return true;
            default:
                return false;
            }
        }

        public static bool IsUnicodeWhitespace(int chr)
        {
            switch (chr)
            {
            case '\t': case '\n': case '\v': case '\f': case '\r': case ' ':
            case '\u0085': case '\u00A0': case '\u1680': case '\u2000':
            case '\u2001': case '\u2002': case '\u2003': case '\u2004':
            case '\u2005': case '\u2006': case '\u2007': case '\u2008':
            case '\u2009': case '\u200A': case '\u2028': case '\u2029':
            case '\u202F': case '\u205F': case '\u3000':
                return true;
            default:
                return false;
            }
        }

        public static bool IsNewLine(int chr)
        {
            switch (chr)
            {
            case '\n': case '\v': case '\f': case '\r':
            case '\u0085': case '\u2028': case '\u2029':
                return true;
            default:
                return false;
            }
        }

        public static WhitespaceInfo GetWhitespaceInfo(int chr)
        {
            switch (chr)
            {
            //   CHAR       ------------BOILERPLATE-----------  BREAK   NEWLINE
            case '\t':      return new WhitespaceInfo('\t',     true,   false);
            case '\n':      return new WhitespaceInfo('\n',     false,  true);
            case '\v':      return new WhitespaceInfo('\v',     false,  true);
            case '\f':      return new WhitespaceInfo('\f',     false,  true);
            case '\r':      return new WhitespaceInfo('\r',     false,  true);
            case ' ':       return new WhitespaceInfo(' ',      true,   false);
            case '\u0085':  return new WhitespaceInfo('\u0085', false,  true);
            case '\u00A0':  return new WhitespaceInfo('\u00A0', false,  false);
            case '\u1680':  return new WhitespaceInfo('\u1689', true,   false);
            case '\u2000':  return new WhitespaceInfo('\u2000', true,   false);
            case '\u2001':  return new WhitespaceInfo('\u2001', true,   false);
            case '\u2002':  return new WhitespaceInfo('\u2002', true,   false);
            case '\u2003':  return new WhitespaceInfo('\u2003', true,   false);
            case '\u2004':  return new WhitespaceInfo('\u2004', true,   false);
            case '\u2005':  return new WhitespaceInfo('\u2005', true,   false);
            case '\u2006':  return new WhitespaceInfo('\u2006', true,   false);
            case '\u2007':  return new WhitespaceInfo('\u2007', false,  false);
            case '\u2008':  return new WhitespaceInfo('\u2008', true,   false);
            case '\u2009':  return new WhitespaceInfo('\u2009', true,   false);
            case '\u200A':  return new WhitespaceInfo('\u200A', true,   false);
            case '\u2028':  return new WhitespaceInfo('\u2028', false,  true);
            case '\u2029':  return new WhitespaceInfo('\u2029', false,  true);
            case '\u202F':  return new WhitespaceInfo('\u202F', false,  false);
            case '\u205F':  return new WhitespaceInfo('\u205F', true,   false);
            case '\u3000':  return new WhitespaceInfo('\u3000', true,   false);
            case '\u180E':  return new WhitespaceInfo('\u180E', true,   false);
            case '\u200B':  return new WhitespaceInfo('\u200B', true,   false);
            case '\u200C':  return new WhitespaceInfo('\u200C', true,   false);
            case '\u200D':  return new WhitespaceInfo('\u200D', true,   false);
            case '\u2060':  return new WhitespaceInfo('\u2060', false,  false);
            default:
                throw new ArgumentException("Character is not a whitespace character.", nameof(chr));
            }
        }
    }

    public struct WhitespaceInfo
    {
        public int Character { get; }
        public bool IsBreaking { get; }
        public bool IsNewline { get; }

        public WhitespaceInfo(int chr, bool breaking, bool nl)
        {
            Character = chr;
            IsBreaking = breaking;
            IsNewline = nl;
        }
    }
}