import os


from Ft.Ods.StorageManager.Adapters import Constants
from Ft.Ods import Database, Structure, Collections

import os,sys
import test_util

odl_string = """
module Test {

  struct ZipCode {
    string zip;
    string plus4;
  };

  enum State {AL,CO,WI};

  class Postman;

  struct Address {
    struct Streets {string street1; string street2; struct another {string foo;} more;} street;
    string city;
    State state;
    ZipCode zip;
    Postman thePostman;
    list <string> poBoxes;
    enum TestEnum {One, Two, Three} testEnum;
  };

  class Person {
    attribute string name;
    attribute Address address;
  };

  class Postman extends Person {
    attribute string routeId;
  };

};

"""
#"


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('Structure Test %s driver' % tester.test_data['driver'])

    test_util.DbInit(DBNAME,odl_string)

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

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

        tester.startTest('Testing Structure Creation')

        p = Person.new(db)
        pm = Postman.new(db)

        p.name = 'Mike Olson'
        pm.name = 'Mr. Postman'

        if db.lookup('Person'):
            db.unbind('Person')
        db.bind(p,'Person')

        tester.compare(1,hasattr(p.address,'street'))
        tester.compare(1,isinstance(p.address.street,Structure.Structure))
        tester.compare(1,isinstance(p.address.street.more,Structure.Structure))
        tester.compare(1,hasattr(p.address.street,'street1'))
        tester.compare(1,hasattr(p.address.street,'street2'))

        tester.compare(1,hasattr(p.address,'city'))

        tester.compare(1,hasattr(p.address,'state'))
        tester.compare(Test.State.elements[0],p.address.state)


        tester.compare(1,hasattr(p.address,'zip'))
        tester.compare(1,isinstance(p.address.zip,Structure.Structure))
        tester.compare(1,hasattr(p.address.zip,'zip'))
        tester.compare(1,hasattr(p.address.zip,'plus4'))

        tester.compare(1,hasattr(p.address,'thePostman'))
        tester.compare(None,p.address.thePostman)


        tester.compare(1,hasattr(p.address,'poBoxes'))
        tester.compare(1,isinstance(p.address.poBoxes,Collections.LiteralListOfValues))

        tester.compare(1,hasattr(p.address,'testEnum'))
        tester.compare(Test.Address.TestEnum.elements[0],p.address.testEnum)


        p.address.street.street1 = "Street 1"
        p.address.street.street2 = "Street 2"
        p.address.street.more.foo = "Foo"
        p.address.city = "A City"
        p.address.state = Test.State.elements[1]
        p.address.zip.zip = 'A Zip'
        p.address.zip.plus4 = 'Plus 4'

        p.address.thePostman = pm

        p.address.poBoxes.append("1234")

        p.address.testEnum = Test.Address.TestEnum.Two

        tx.commit()
        tester.testDone()


        tester.startTest('Testing access and modify Structure')
        tx = db.new()
        tx.begin()

        p = db.lookup('Person')

        tester.compare("Street 1",p.address.street.street1)
        tester.compare("Street 2",p.address.street.street2)
        tester.compare("Foo",p.address.street.more.foo)
        tester.compare("A City",p.address.city)
        tester.compare(Test.State.elements[1],p.address.state)
        tester.compare("A Zip",p.address.zip.zip)
        tester.compare("Plus 4",p.address.zip.plus4)

        tester.compare("Mr. Postman",p.address.thePostman.name)

        tester.compare(1,len(p.address.poBoxes))
        tester.compare(1,p.address.poBoxes.contains_element('1234'))

        tester.compare(Test.Address.TestEnum.elements[1],p.address.testEnum)

        #Change them all
        p.address.street.street1 = "Another Street 1"
        p.address.street.street2 = "Another Street 2"
        p.address.street.more.foo = "Another Foo"
        p.address.city = "Another City"
        p.address.state = Test.State.elements[2]
        p.address.zip.zip = "Another Zip"
        p.address.zip.plus4 = "Another Plus 4"

        pm = Postman.new(db)
        pm.name = 'Mr. Postman the Second'
        p.address.thePostman = pm

        p.address.poBoxes.append("4321")
        p.address.testEnum = Test.Address.TestEnum.Three


        tx.commit()
        tester.testDone()

        tester.startTest('Testing modified Structure')
        tx = db.new()
        tx.begin()

        p = db.lookup('Person')

        tester.compare("Another Street 1",p.address.street.street1)
        tester.compare("Another Street 2",p.address.street.street2)
        tester.compare("Another Foo",p.address.street.more.foo)
        tester.compare("Another City",p.address.city)
        tester.compare(Test.State.elements[2],p.address.state)
        tester.compare("Another Zip",p.address.zip.zip)
        tester.compare("Another Plus 4",p.address.zip.plus4)

        tester.compare("Mr. Postman the Second",p.address.thePostman.name)

        tester.compare(2,len(p.address.poBoxes))
        tester.compare(1,p.address.poBoxes.contains_element('1234'))
        tester.compare(1,p.address.poBoxes.contains_element('4321'))

        p.address.testEnum = Test.Address.TestEnum.Three

        tx.commit()
        tester.testDone()

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

    return

