class Style(object):
    def __init__(self, name, env=False, link=False):
        self.name = name
        self.env = env
        self.link = link
        self.selfenv = False
    def __repr__(self):
        return '[%s]' % self.name
class Environment(Style):
    def __init__(self, name, group=None):
        Style.__init__(self, name, env=True)
        self.group = group
        self.selfenv = True

# Environments
PARAGRAPH = Environment('PARAGRAPH')
ORDERED = Environment('ORDERED', group='list')
UNORDERED = Environment('UNORDERED', group='list')
BLOCKQUOTE = Environment('BLOCKQUOTE', group='blockquote')
TABLE = Environment('TABLE')

# Markup
BOLD = Style('BOLD')
ITALIC = Style('ITALIC')
MONOSPACE = Style('MONOSPACE')
SUPERSCRIPT = Style('SUPERSCRIPT')
SUBSCRIPT = Style('SUBSCRIPT')
UNDERLINE = Style('UNDERLINE')
STRIKE = Style('STRIKE')
CODEBLOCK = Style('CODEBLOCK', env=True)
HEADING = Style('HEADING', env=True)

# Non-Creole markup
CENTER = Style('CENTER', env=True)
RIGHT = Style('RIGHT', env=True)
NOINDENT = Style('NOINDENT', env=None)
FOOTNOTE = Style('FOOTNOTE')

# Takes a size arg from -4 to 5
SIZE = Style('SIZE')

LINK = Style('LINK', link=True)
IMAGE = Style('IMAGE', link=True)

ORDERED_ITEM = Style('ORDERED_ITEM', env=ORDERED)
UNORDERED_ITEM = Style('UNORDERED_ITEM', env=UNORDERED)
BLOCKQUOTE_LINE = Style('BLOCKQUOTE_LINE', env=BLOCKQUOTE)

# Rows transition to the TABLE environment; cells don't need to.
TABLE_ROW = Style('TABLE_ROW', env=TABLE)
TABLE_HEADING = Style('TABLE_HEADING', env=True)
TABLE_CELL = Style('TABLE_CELL', env=True)

HRULE = Style('HRULE')
LINEBREAK = Style('LINEBREAK')
ENV_BREAK = Style('ENV_BREAK', env=None)

REF = Style('REF')

MACRO = Style('MACRO')

ERROR = Style('ERROR')

class Op(object):
    def __init__(self, name):
        self.name = name
    def __repr__(self):
        return '<%s>' % self.name

START = Op('Start')
END = Op('End')
ENTITY = Op('Entity')
TEXT = Op('Text')
LITERAL = Op('Literal')

class Token(object):
    def __init__(self, op, style=None, arg=None):
        assert style is None or isinstance(style, Style), style
        self.op = op
        self.style = style
        self.arg = arg
        if style and style.link:
            assert isinstance(arg, unicode)
    def __repr__(self):
        return "<Token %s %s(%s)>" % (self.op, repr(self.style),
                                      repr(self.arg))
    # For test assertions.
    def __eq__(self, other):
        try:
            return (self.op == other.op and self.style == other.style
                    and self.arg == other.arg)
        except AttributeError:
            return False
    def __ne__(self, other):
        return not self.__eq__(other)

def Start(style, arg=None):
    return Token(START, style, arg)
def End(style, arg=None):
    return Token(END, style, arg)
def Entity(entity, arg=None):
    return Token(ENTITY, entity, arg)
def Text(text):
    assert isinstance(text, unicode), repr(text)
    return Token(TEXT, arg=text)
def Literal(output):
    return Token(LITERAL, arg=output)
