#!/usr/bin/python

__all__ = (
    'parse_checks',
    'BooleanParser',
    'ParseException'
)

try:
    from pyparsing import alphanums
    from pyparsing import alphas
    from pyparsing import Dict
    from pyparsing import Group
    from pyparsing import opAssoc
    from pyparsing import operatorPrecedence
    from pyparsing import Optional
    from pyparsing import ParseException
    from pyparsing import QuotedString
    from pyparsing import Suppress
    from pyparsing import Word
    from pyparsing import ZeroOrMore
except ImportError:
    from utils.pyparsing import alphanums
    from utils.pyparsing import alphas
    from utils.pyparsing import Dict
    from utils.pyparsing import Group
    from utils.pyparsing import opAssoc
    from utils.pyparsing import operatorPrecedence
    from utils.pyparsing import Optional
    from utils.pyparsing import ParseException
    from utils.pyparsing import QuotedString
    from utils.pyparsing import Suppress
    from utils.pyparsing import Word
    from utils.pyparsing import ZeroOrMore


def __make_parser():
    key = Word(alphas, alphanums + "_-")
    value = Word(alphanums + "-.,_=<>!@$%^&*[]{}:;|/'") | QuotedString('"')
    return Dict(
        ZeroOrMore(
            Group(key + Optional(Suppress("=") + value, default=True))
        )
    )


__checkparser = __make_parser()


def parse_checks(string):
    """
    from parsers import parse_checks
    >>> parse_checks(
        'dependent=5a,no dependent="5a && 4a" dog="Roaming Rover" '
        'name=Robert foo bar'
    )
    (
        [
            (['dependent', '5a,no'], {}),
            (['dependent', '5a && 4a'], {}),
            (['dog', 'Roaming Rover'], {}),
            (['name', 'Robert'], {}),
            (['foo', True], {}),
            (['bar', True], {})
        ], {
            'dependent': [('5a,no', 0), ('5a && 4a', 1)],
            'foo': [(True, 4)],
            'bar': [(True, 5)],
            'dog': [('Roaming Rover', 2)],
            'name': [('Robert', 3)]
        }
    )
    """
    return __checkparser.parseString(string, parseAll=True)


# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-
# - Boolean Expression Parser -
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-

class BoolOperand(object):

    def __init__(self, t):
        self.args = t[0][0::2]

    def __str__(self):
        sep = " %s " % self.reprsymbol
        return "(" + sep.join(map(str, self.args)) + ")"


class BoolAnd(BoolOperand):

    reprsymbol = '&&'

    def __nonzero__(self):
        for a in self.args:
            if not bool(a):
                return False
        return True


class BoolOr(BoolOperand):

    reprsymbol = '||'

    def __nonzero__(self):
        for a in self.args:
            if bool(a):
                return True
        return False


class BoolNot(BoolOperand):