"""Example provided by Brad Chapman (chapmanb@arches.uga.edu) 2000-12-12 that found many bugs in ODS collections
"""
import random, os, sys
from Ft.Ods import Database
from Ods.System import test_util


odl_string="""module Divorce {

  class Child;
  class Parent;

  class DysfunctionalFamily {
    relationship list<Parent> parents inverse Parent::family;
  };

  class Parent {
    attribute string name;
    relationship list<Child> kids inverse Child::parent;
    relationship DysfunctionalFamily family inverse 
      DysfunctionalFamily::parents;
  };

  class Child {
    attribute string name;
    relationship Parent my_parent inverse Parent::kids;
  };
};"""
#"

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


def load_db(tester):
    test_util.DbInit(DBNAME,odl_string)


    tester.startTest('Testing Generated syntax')
    try:
        from Divorce import Child
        from Divorce import Parent
        from Divorce import DysfunctionalFamily
    except:
        tester.error('Error in syntax', 1)

    tester.testDone()
    tester.startTest("Load DB")
    db = Database.Database()
    db.open(DBNAME)
    try:
        tx = db.new()
        tx.begin()

        # create the family and the parents
        divorce_family = DysfunctionalFamily.new(db)
        mom = Parent.new(db)
        mom.name = 'Mom'
        dad = Parent.new(db)
        dad.name = 'Dad'

        if db.lookup('mom'):
            db.unbind('mom')
        db.bind(mom,'mom')
        if db.lookup('dad'):
            db.unbind('dad')
        db.bind(dad,'dad')

        divorce_family.add_parents(mom)
        divorce_family.add_parents(dad)

        # now create the kids and assign 'em to parents
        all_kids = ['Bobby', 'Tommy', 'Marissa', 'Aaron', 'Joni',
                    'Strom', 'Ani', 'Jim', 'Maryrose', 'Mary']

        # give Mom some kids
        for name in all_kids[:5]:
            new_kid = Child.new(db)
            new_kid.name = name
            if db.lookup(name):
                db.unbind(name)
            db.bind(new_kid,name)
            mom.add_kids(new_kid)

        # Dad wants some too
        for name in all_kids[5:]:
            new_kid = Child.new(db)
            new_kid.name = name
            if db.lookup(name):
                db.unbind(name)
            db.bind(new_kid,name)
            dad.add_kids(new_kid)

        if db.lookup('our_family'):
            db.unbind('our_family')
        db.bind(divorce_family, "our_family")

        tx.commit()
    finally:
        db.close()
    tester.testDone()


def swap_kid(tester,parent, other_parent):
    """Swap a kid from one parent to the other parent.
    """
    # pick the kid to switch
    kid_to_swap = random.choice(parent.kids)
    
    # now switch 'em and commit it
    parent.remove_kids(kid_to_swap)
    other_parent.add_kids(kid_to_swap)
    tester.testResults(1,other_parent.kids.contains_element(kid_to_swap),done=0)
    tester.testResults(0,parent.kids.contains_element(kid_to_swap),done=0)


def do_test(tester):


    # keep switching kids around
    db = Database.Database()
    db.open(DBNAME)
    try:
        tester.startTest("Child Swapping")
        for i in range(10):
            tx = db.new()
            tx.begin()
            family = db.lookup("our_family")
            swap_kid(tester,family.parents[0], family.parents[1])
            tx.commit()
            tx = db.new()
            tx.begin()
            family = db.lookup("our_family")
            swap_kid(tester,family.parents[1], family.parents[0])
            tx.commit()
        tester.testDone()
    finally:
        db.close()

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


def _Test(tester):
    tester.startGroup("Borrowed bc_2000-12-12")
    load_db(tester)
    do_test(tester)
    tester.groupDone()

    

