# Path: format_sql/parser.py
# class Between(object):
#     value = attr.ib()
# 
# class Case(object):
#     value = attr.ib()
#     when_elses = attr.ib()
# 
# class Condition(object):
#     values = attr.ib()
# 
# class Else(object):
#     else_ = attr.ib()
#     result = attr.ib()
# 
#     def __str__(self):
#         return 'ELSE %s' % self.result
# 
# class From(object):
#     value = attr.ib()
#     values = attr.ib()
# 
# class Func(object):
#     name = attr.ib()
#     args = attr.ib()
#     as_ = attr.ib(default=None)
#     alias = attr.ib(default=None)
# 
# class GroupBy(object):
#     values = attr.ib()
#     with_rollup = attr.ib(default=None)
# 
# class Having(object):
#     value = attr.ib()
#     values = attr.ib()
# 
# class Identifier(object):
#     value = attr.ib()
#     alias = attr.ib(default=None)
#     as_ = attr.ib(default=None)
#     sort = attr.ib(default=None)
# 
#     def __str__(self):
#         return '%s' % self.value
# 
# class Insert(object):
#     insert = attr.ib()
#     table = attr.ib()
#     values = attr.ib(default=[])
#     cols = attr.ib(default=[])
#     select = attr.ib(default=[])
# 
# class InvalidSQL(Exception):
#     pass
# 
# class Is(object):
#     value = attr.ib()
# 
# class Join(object):
#     value = attr.ib()
# 
# class Limit(object):
#     row_count = attr.ib()
#     offset = attr.ib(default=None)
#     offset_keyword = attr.ib(default=None)
# 
# class Link(object):
#     value = attr.ib()
# 
# class Not(object):
#     value = attr.ib()
# 
# class Null(object):
#     value = attr.ib()
# 
# class Number(object):
#     value = attr.ib()
#     alias = attr.ib(default=None)
#     as_ = attr.ib(default=None)
#     sort = attr.ib(default=None)
# 
#     def __str__(self):
#         return '%s' % self.value
# 
# class On(object):
#     value = attr.ib()
#     values = attr.ib(default=[])
# 
# class Operator(object):
#     value = attr.ib()
# 
#     def __str__(self):
#         return '%s' % self.value.upper()
# 
# class OrderBy(object):
#     values = attr.ib()
# 
# class Select(object):
#     value = attr.ib()
#     values = attr.ib()
# 
# class Semicolon(object):
#     value = attr.ib()
# 
# class Str(object):
#     value = attr.ib()
#     alias = attr.ib(default=None)
#     as_ = attr.ib(default=None)
#     sort = attr.ib(default=None)
# 
#     def __str__(self):
#         return '%s' % self.value
# 
# class SubSelect(object):
#     values = attr.ib()
# 
# class When(object):
#     when = attr.ib()
#     condition = attr.ib()
#     then = attr.ib()
#     result = attr.ib()
# 
#     def __str__(self):
#         return 'WHEN %s THEN %s' % (self.condition, self.result)
# 
# class Where(object):
#     value = attr.ib()
#     conditions = attr.ib()


from format_sql.parser import (Between, Case, Condition, Else, From, Func,
                               GroupBy, Having, Identifier, Insert, InvalidSQL,
                               Is, Join, Limit, Link, Not, Null, Number, On,
                               Operator, OrderBy, Select, Semicolon, Str,
                               SubSelect, When, Where)
        liner.end_line()


def _style_semicolon(semicolon, liner, indent):
    liner.add_to_last_line(semicolon.value)


def style(statements, indent=0, keyword_upper=True, liner=None):
    if not liner:
        liner = Liner()

    structures = {
        From: _style_from,
        GroupBy: _style_group_by,
        Having: _style_having,
        Insert: _style_insert,
        Limit: _style_limit,
        OrderBy: _style_order_by,
        Select: _style_select,
        Semicolon: _style_semicolon,
        Where: _style_where,
    }

    for i, statement in enumerate(statements):
        func = structures[statement.__class__]
        try:
            func(statement, liner=liner, indent=indent)
        except IndexError:
            raise InvalidSQL()


# Path: format_sql/parser.py
# class Between(object):
#     value = attr.ib()
# 
# class Case(object):
#     value = attr.ib()
#     when_elses = attr.ib()
# 
# class Condition(object):
#     values = attr.ib()
# 
# class Else(object):
#     else_ = attr.ib()
#     result = attr.ib()
# 
#     def __str__(self):
#         return 'ELSE %s' % self.result
# 
# class From(object):
#     value = attr.ib()
#     values = attr.ib()
# 
# class Func(object):
#     name = attr.ib()
#     args = attr.ib()
#     as_ = attr.ib(default=None)
#     alias = attr.ib(default=None)
# 
# class GroupBy(object):
#     values = attr.ib()
#     with_rollup = attr.ib(default=None)
# 
# class Having(object):
#     value = attr.ib()
#     values = attr.ib()
# 
# class Identifier(object):
#     value = attr.ib()
#     alias = attr.ib(default=None)
#     as_ = attr.ib(default=None)
#     sort = attr.ib(default=None)
# 
#     def __str__(self):
#         return '%s' % self.value
# 
# class Insert(object):
#     insert = attr.ib()
#     table = attr.ib()
#     values = attr.ib(default=[])
#     cols = attr.ib(default=[])
#     select = attr.ib(default=[])
# 
# class InvalidSQL(Exception):
#     pass
# 
# class Is(object):
#     value = attr.ib()
# 
# class Join(object):
#     value = attr.ib()
# 
# class Limit(object):
#     row_count = attr.ib()
#     offset = attr.ib(default=None)
#     offset_keyword = attr.ib(default=None)
# 
# class Link(object):
#     value = attr.ib()
# 
# class Not(object):
#     value = attr.ib()
# 
# class Null(object):
#     value = attr.ib()
# 
# class Number(object):
#     value = attr.ib()
#     alias = attr.ib(default=None)
#     as_ = attr.ib(default=None)
#     sort = attr.ib(default=None)
# 
#     def __str__(self):
#         return '%s' % self.value
# 
# class On(object):
#     value = attr.ib()
#     values = attr.ib(default=[])
# 
# class Operator(object):
#     value = attr.ib()
# 
#     def __str__(self):
#         return '%s' % self.value.upper()
# 
# class OrderBy(object):
#     values = attr.ib()
# 
# class Select(object):
#     value = attr.ib()
#     values = attr.ib()
# 
# class Semicolon(object):
#     value = attr.ib()
# 
# class Str(object):
#     value = attr.ib()
#     alias = attr.ib(default=None)
#     as_ = attr.ib(default=None)
#     sort = attr.ib(default=None)
# 
#     def __str__(self):
#         return '%s' % self.value
# 
# class SubSelect(object):
#     values = attr.ib()
# 
# class When(object):
#     when = attr.ib()
#     condition = attr.ib()
#     then = attr.ib()
#     result = attr.ib()
# 
#     def __str__(self):
#         return 'WHEN %s THEN %s' % (self.condition, self.result)
# 
# class Where(object):
#     value = attr.ib()
#     conditions = attr.ib()


# Path: format_sql/styler.py
from format_sql.parser import (Between, Case, Condition, Else, From, Func,
                               GroupBy, Having, Identifier, Insert, InvalidSQL,
                               Is, Join, Limit, Link, Not, Null, Number, On,
                               Operator, OrderBy, Select, Semicolon, Str,
                               SubSelect, When, Where)

        liner.end_line()


def _style_semicolon(semicolon, liner, indent):
    liner.add_to_last_line(semicolon.value)


def style(statements, indent=0, keyword_upper=True, liner=None):
    if not liner:
        liner = Liner()

    structures = {
        From: _style_from,
        GroupBy: _style_group_by,
        Having: _style_having,
        Insert: _style_insert,
        Limit: _style_limit,
        OrderBy: _style_order_by,
        Select: _style_select,
        Semicolon: _style_semicolon,
        Where: _style_where,
    }

    for i, statement in enumerate(statements):
        func = structures[statement.__class__]
        try:
            func(statement, liner=liner, indent=indent)
        except IndexError:
            raise InvalidSQL()


        if isinstance(statement, Semicolon) and len(statements) > i + 1: