# Path: stripstream/fts/variable.py
# class FreeParameter(SSParameter):
#     num = 0
#     prefix = '_param%s'
# 
#     def __init__(self, name, type=None):
#         if type is None:
#             type = name
#             assert isinstance(type, VarType)
#             name = self.prefix % FreeParameter.num
#             FreeParameter.num += 1
#         super(FreeParameter, self).__init__(name, type)
# 
# def is_constant(v):
#     return not is_parameter(v)
# 
# Path: stripstream/pddl/logic/predicates.py
# class Predicate(Head):
#     pass
#     """
#   Predicate P which extends :class:`.NamedHead`.
#   """
# 
# Path: stripstream/pddl/objects.py
# OBJECT = Type('object')
# 
# Path: stripstream/pddl/cond_streams.py
# class ExternalTestCondStream(TestCondStream):
# 
#     def __init__(self, test, name=None, *args, **kwargs):
#         self.test = test
#         super(ExternalTestCondStream, self).__init__(*args, **kwargs)
#         if name is not None:
#             self.name = name
# 
#     class StreamFn(TestStream):
# 
#         def __init__(self, cs, inputs, **kwargs):
#             self.test = cs.test
#             TestStream.__init__(self, cs, inputs, **kwargs)


from stripstream.fts.variable import FreeParameter, is_constant
from stripstream.pddl.logic.predicates import Predicate
from stripstream.pddl.objects import OBJECT
from stripstream.pddl.cond_streams import ExternalTestCondStream

class ConstraintType(object):
    num = 0

    prefix = 'Con%s'

    def __init__(self, types=(), test=None, domain=(), satisfying=(), name=None, **kwargs):
        self.types = tuple(types)
        self.test = test
        self.n = ConstraintType.num
        ConstraintType.num += 1
        self.name = name if name is not None else self.prefix % self.n
        self.domain = tuple(domain)
        self.satisfying = tuple(satisfying)
        self.predicate = Predicate(self.name, self.types)
        self.kwargs = kwargs

    def __call__(self, *args, **kwargs):
        return Constraint(self, args)

    def __repr__(self):
        return self.name

ConType = ConstraintType


Eq = ConType([OBJECT, OBJECT], test=lambda a, b: a == b, name='Eq')


Identity = ConType([OBJECT], test=lambda a: True, name='Identity')

# Path: stripstream/fts/variable.py
# class FreeParameter(SSParameter):
#     num = 0
#     prefix = '_param%s'
# 
#     def __init__(self, name, type=None):
#         if type is None:
#             type = name
#             assert isinstance(type, VarType)
#             name = self.prefix % FreeParameter.num
#             FreeParameter.num += 1
#         super(FreeParameter, self).__init__(name, type)
# 
# def is_constant(v):
#     return not is_parameter(v)
# 
# Path: stripstream/pddl/logic/predicates.py
# class Predicate(Head):
#     pass
#     """
#   Predicate P which extends :class:`.NamedHead`.
#   """
# 
# Path: stripstream/pddl/objects.py
# OBJECT = Type('object')
# 
# Path: stripstream/pddl/cond_streams.py
# class ExternalTestCondStream(TestCondStream):
# 
#     def __init__(self, test, name=None, *args, **kwargs):
#         self.test = test
#         super(ExternalTestCondStream, self).__init__(*args, **kwargs)
#         if name is not None:
#             self.name = name
# 
#     class StreamFn(TestStream):
# 
#         def __init__(self, cs, inputs, **kwargs):
#             self.test = cs.test
#             TestStream.__init__(self, cs, inputs, **kwargs)


# Path: stripstream/fts/constraint.py
from stripstream.fts.variable import FreeParameter, is_constant
from stripstream.pddl.logic.predicates import Predicate
from stripstream.pddl.objects import OBJECT
from stripstream.pddl.cond_streams import ExternalTestCondStream


class ConstraintType(object):
    num = 0

    prefix = 'Con%s'

    def __init__(self, types=(), test=None, domain=(), satisfying=(), name=None, **kwargs):
        self.types = tuple(types)
        self.test = test
        self.n = ConstraintType.num
        ConstraintType.num += 1
        self.name = name if name is not None else self.prefix % self.n
        self.domain = tuple(domain)
        self.satisfying = tuple(satisfying)
        self.predicate = Predicate(self.name, self.types)
        self.kwargs = kwargs

    def __call__(self, *args, **kwargs):
        return Constraint(self, args)

    def __repr__(self):
        return self.name

ConType = ConstraintType


Eq = ConType([OBJECT, OBJECT], test=lambda a, b: a == b, name='Eq')


Identity = ConType([OBJECT], test=lambda a: True, name='Identity')

Unconstrained = ConType([OBJECT], test=lambda a: True, name='Unconstrained')