from Node import error
from kinds import lowercase_first_word  # noqa: I201


class Trivia(object):
    def __init__(self, name, comment, serialization_code, characters=[],
                 swift_characters=[], is_new_line=False, is_comment=False):
        self.name = name
        self.comment = comment
        self.serialization_code = serialization_code
        self.characters = characters
        self.lower_name = lowercase_first_word(name)
        self.is_new_line = is_new_line
        self.is_comment = is_comment

        # Swift sometimes doesn't support escaped characters like \f or \v;
        # we should allow specifying alternatives explicitly.
        self.swift_characters = swift_characters if swift_characters else\
            characters
        assert len(self.swift_characters) == len(self.characters)

    def characters_len(self):
        return len(self.characters)

    def is_collection(self):
        return self.characters_len() > 0


TRIVIAS = [
    Trivia('Space', 'A space \' \' character.', characters=[' '],
           serialization_code=0),
    Trivia('Tab', 'A tab \'\\t\' character.', characters=['\\t'],
           serialization_code=1),
    Trivia('VerticalTab', 'A vertical tab \'\\v\' character.',
           characters=['\\v'], swift_characters=['\\u{2B7F}'],
           serialization_code=2),
    Trivia('Formfeed', 'A form-feed \'f\' character.', characters=['\\f'],
           swift_characters=['\\u{240C}'], serialization_code=3),
    Trivia('Newline', 'A newline \'\\n\' character.', characters=['\\n'],
           is_new_line=True, serialization_code=4),
    Trivia('CarriageReturn', 'A newline \'\\r\' character.',
           characters=['\\r'], is_new_line=True, serialization_code=5),
    Trivia('CarriageReturnLineFeed',
           'A newline consists of contiguous \'\\r\' and \'\\n\' characters.',
           characters=['\\r', '\\n'], is_new_line=True, serialization_code=6),
    Trivia('Backtick',
           'A backtick \'`\' character, used to escape identifiers.',
           characters=['`'], serialization_code=7),
    Trivia('LineComment', 'A developer line comment, starting with \'//\'',
           is_comment=True, serialization_code=8),
    Trivia('BlockComment',
           'A developer block comment, starting with \'/*\' and ending with'
           ' \'*/\'.',
           is_comment=True, serialization_code=9),
    Trivia('DocLineComment',
           'A documentation line comment, starting with \'///\'.',
           is_comment=True, serialization_code=10),
    Trivia('DocBlockComment',
           'A documentation block comment, starting with \'/**\' and ending '
           'with \'*/\'.',
           is_comment=True, serialization_code=11),
    Trivia('GarbageText', 'Any skipped garbage text.', serialization_code=12),
]


def verify_no_duplicate_serialization_codes(trivias):
    used_codes = set()
    for trivia in trivias:
        if trivia.serialization_code in used_codes:
            error("Serialization code %d used twice for trivia" %
                  trivia.serialization_code)
        used_codes.add(trivia.serialization_code)


verify_no_duplicate_serialization_codes(TRIVIAS)
