from Ft.Rdf.Drivers import Memory
from Ft.Rdf import Model
import cStringIO

def CreateInfEng():
    from Ft.Rdf.Inference import InferenceEngine
    db = Memory.DbAdapter('kb')
    db.begin()
    kb = Model.Model(db)
    return InferenceEngine.InferenceEngine(kb)

def Test(test):
    test.startGroup('InferenceEngine')
    
    test.startTest('Syntax')
    if 1:
    #try:
        from Ft.Rdf.Inference import InferenceEngine
        from Ft.Rdf.Inference import Common
        from Ft.Rdf.Inference import Predicate
        from Ft.Rdf.Inference import Rule
        from Ft.Rdf.Inference import Query
        from Ft.Rdf.Inference import Action
        from Ft.Rdf.Inference import Assert
        from Ft.Rdf.Inference import Command

    #except:
    #    test.error('Error in syntax', 1)
    test.testDone()

    #Try to do a pretty full test
    #param runners=['Uche','Mike']
    #AGE(Mike,26)
    #AGE(Uche,29)
    #if running($X) then sweating($X);
    #if sweating($X) then wet($X);
    #RUNNING(runners);
    #Z=Sort(AGE(Subject(WET($X))),NUMBER)
    #MESSAGE $Z
    #Z
    #AVE(Object(Z))

    test.startTest('Basic Inference')

    #Create the external param
    defs = []
    sl = Common.StringListLiteralArgument('foo',["Uche",'Mike'])
    params = Action.ExternalParamAction("runners",sl)
    defs.append(params)

    #Assert the ages
    sl2 = Common.StringLiteralArgument('foo',"Uche")
    sl3 = Common.StringLiteralArgument('foo',"29")
    ages = Assert.DualAssert("AGE",0,(sl2,sl3))
    defs.append(ages)
    sl2 = Common.StringLiteralArgument('foo',"Mike")
    sl3 = Common.StringLiteralArgument('foo',"26")
    ages = Assert.DualAssert("AGE",0,(sl2,sl3))
    defs.append(ages)

    #Add the first rule
    sv = Common.SkolemVariableArgument("X")
    p = Predicate.AndSinglePredicate('RUNNING',(sv,))
    a = Assert.SingleAssert('SWEATING',0,(sv,))
    r = Rule.Rule("Rule 1",[p],[a])
    defs.append(r)

    #Add the sceond Rule
    sv = Common.SkolemVariableArgument("X")
    p = Predicate.AndSinglePredicate('SWEATING',(sv,))
    a = Assert.SingleAssert('WET',0,(sv,))
    r = Rule.Rule("Rule 2",[p],[a])
    defs.append(r)

    #Assert the runners
    sl4 = Common.VariableReferenceArgument("runners")
    run = Assert.SingleAssert("RUNNING",0,(sl4,))
    defs.append(run)

    #The big sort mess
    sv = Common.SkolemVariableArgument("X")
    wet = Query.SingleQuery('WET',(sv,))
    subs = Action.StatementSubject(wet)
    ages = Query.SingleQuery('AGE',(subs,))
    sort = Action.SortAction(ages,Action.SortType.NUMBER_SORT)
    set = Action.VariableSetAction('z',sort)
    defs.append(set)

    #Message Z
    v = Common.VariableReferenceArgument('z')
    mes = Command.MessageCommand((v,))
    defs.append(mes)

    #Return z
    defs.append(v)

    #Return the average
    v = Common.VariableReferenceArgument('z')
    objs = Action.StatementObject(v)
    ave = Action.AverageAction(objs)
    defs.append(ave)

    infeng = CreateInfEng()

    st = cStringIO.StringIO()
    infeng.outStream = st
    res = infeng.execute(defs)

    test.compare([[('Mike', 'AGE', '26'), ('Uche', 'AGE', '29')], ['27.5']],res)

    import sys
    if sys.hexversion >= 0x2000000:

        expected = """**Start Ril Message**
[(u'Mike', u'AGE', u'26'), (u'Uche', u'AGE', u'29')]
**End Ril Message**
"""
    else:
        expected = """**Start Ril Message**
[('Mike', 'AGE', '26'), ('Uche', 'AGE', '29')]
**End Ril Message**
"""

    test.compare(expected,st.getvalue())
    
    test.testDone()
    test.groupDone()


if __name__ == '__main__':
    import sys
    from Ft.Lib import TestSuite

    testmgr = TestSuite.TestSuite()
    ret_val = Test(testmgr)
    sys.exit(ret_val)

