DELIMITER = '__'

class InvalidOperatorError(Exception):
    pass

compare_str = cmp


def is_int(value):
    try:
        int(value)
        return True
    except (ValueError, TypeError):
        return False


class Lookup(object):

    def contains(self, index, value):
        return lambda x: value in x[index]

    def icontains(self, index, value):
        return lambda x: value.lower() in x[index].lower()

    def gt(self, index, value):
        return lambda x: int(x[index]) > int(value)

    def igt(self, index, value):
        return lambda x: compare_str(x[index].lower(), value.lower()) > 0

    def ge(self, index, value):
        return lambda x: int(x[index]) >= int(value)

    def ige(self, index, value):
        return lambda x: compare_str(x[index].lower(), value.lower()) >= 0

    def lt(self, index, value):
        return lambda x: int(x[index]) < int(value)

    def ilt(self, index, value):
        return lambda x: compare_str(x[index].lower(), value.lower()) < 0

    def le(self, index, value):
        return lambda x: int(x[index]) <= int(value)

    def ile(self, index, value):
        return lambda x: compare_str(x[index].lower(), value.lower()) <= 0

    def eq(self, index, value):
        if is_int(value):
            return lambda x: int(value) == int(x[index])
        return lambda x: value == x[index]

    def ieq(self, index, value):
        return lambda x: value.lower() == x[index].lower()

    def ne(self, index, value):
        if is_int(value):
            return lambda x: int(value) != int(x[index])
        return lambda x: value != x[index]

    def ine(self, index, value):
        return lambda x: value.lower() != x[index].lower()


def get_lookup(operator, index, value):
    try:
        return getattr(Lookup(), operator)(index, value)
    except (AttributeError,):
        raise InvalidOperatorError('%s is not a valid operator' % operator)
