import os


from Ft.Ods.StorageManager.Adapters import Constants
from Ft.Ods.Exception import FtodsOperationNotImplemented,FtodsOperationBadParam
from Ft.Ods import Database
import os,sys
import test_util
from Ft.Ods.Parsers.Odl import Register
odl_string = """
module Test {

typedef list <float> GradeList;

exception InvalidGrade {
  float grade;
  string reason;
};

class Student (extent students)
{
	attribute string name;
        float calcGPA(in GradeList grades) raises (InvalidGrade);
        long anotherFunc(in short one, inout string two, out float three);
};

};

"""
#"


DBNAME=os.environ.get("ODS_TEST_DB","ods:test")

def Test(tester):
    try:
        _Test(tester)
    finally:
##        if os.path.exists('Test'):
##            from distutils import dir_util
##            dir_util.remove_tree('Test')
        pass

def _Test(tester):

    tester.startGroup('Basic support for operations %s driver' % tester.test_data['driver'])

    test_util.DbInit(DBNAME,odl_string)

    tester.startTest('Testing Generated syntax')
    try:
        from Test import Student
        import Test
    except:
        tester.error('Error in syntax', 1)
    tester.testDone()

    reload(Student)
    reload(Test)
    
    db = Database.Database()
    db.open(DBNAME)
    try:
        tx = db.new()
        tx.begin()

        tester.startTest('Execute a unregistered operation')

        s = Student.new(db)
        s.name = 'Mike Olson'

        gl = Test.GradeList(db)
        gl.insert_element(4)
        gl.insert_element(3)

        tester.testException(s.calcGPA,(gl,),FtodsOperationNotImplemented)
        tester.testException(s.calcGPA,(1,),FtodsOperationBadParam)

        tester.testException(s.anotherFunc,(1,'foo',),FtodsOperationNotImplemented)
        tester.testException(s.anotherFunc,(1,1),FtodsOperationBadParam)

        tx.commit()
        tester.testDone()


        tester.startTest('Test Register of an operation')

        sid = s._4ods_getOid()

        tx = db.new()
        tx.begin()

        import operation_defs
        reload(operation_defs)
        Register.RegisterExtensionModules(db,[operation_defs])

        s = db._4ods_getPersistentObjectById(Constants.Types.POBJECT,sid)

        gl = Test.GradeList(db)
        gl.insert_element(4)
        gl.insert_element(3)

        tester.compare(3.5,s.calcGPA(gl))
        #Run it twice to test the caching
        tester.compare(3.5,s.calcGPA(gl))

        tester.compare((1,'Foo',1.5),s.anotherFunc(1,"foo"))
        tester.compare((1,'Foo',1.5),s.anotherFunc(1,"foo"))

        tx.commit()
        tester.testDone()

        tester.startTest('Test Re-Register of an operation')

        sid = s._4ods_getOid()

        tx = db.new()
        tx.begin()

        operation_defs.g_ftodsOperations['Test::Student::calcGPA'] = operation_defs.CalcGPAImpNeg

        Register.RegisterExtensionModules(db,[operation_defs])

        s = db._4ods_getPersistentObjectById(Constants.Types.POBJECT,sid)

        gl = Test.GradeList(db)
        gl.insert_element(4)
        gl.insert_element(3)

        tester.compare(-3.5,s.calcGPA(gl))
        #Run it twice to test the caching
        tester.compare(-3.5,s.calcGPA(gl))
        tx.commit()
        tester.testDone()


    finally:
        db.close()
    tester.groupDone()


