import unittest
import e4py
import sys


DB_NAME = 'temp.db'


def populateNode(n, d):
	"""
	n - a node
	d - dictionary
	Fills a node from a dictionary.
	All items are added to node as vertices except for dictionaries which represent nodes.
	"""
	for k, v in d.items():
		if type(v) == type({}):
			nn, r = n.AddNode(str(k))
			populateNode(nn, v)
		else:
			n.AddVertex(str(k), e4py.E4_IOLAST, 0, v)


class NodeTest(unittest.TestCase):

	def setUp(self):
		self.storage = e4py.Storage(DB_NAME)
		self.storage.state = self.storage.state & ~e4py.E4_COMMITATCLOSE
		
	def testDetach(self):
		s = self.storage
		r = s.root
		self.assert_(r.VertexCount() == 0)
		populateNode(r, {"n": {}})
		self.assert_(r.VertexCount() == 1)
		n = r['n']
		n.Detach()
		self.assert_(r.VertexCount() == 0)
		
	def testVertexCount(self):
		s = self.storage
		r = s.root
		populateNode(r, {'a': 1, 'b': 'str', 'c': 1.2, 'd': {}})
		self.assert_(r.VertexCount() == 4)

	def testVertexCountWithValue(self):
		s = self.storage
		r = s.root
		populateNode(r, {'a': 1, 'b': '1', 'c': 1.0, 'd': {'e': 1}, 'f': 1})
		self.assert_(r.VertexCountWithValue(1) == 2)

	def testSetNode(self):
		s = self.storage
		r = s.root
		self.failUnlessRaises(e4py.error, r.SetNode, 'a')
		populateNode(r, {'a': 1})
		n = r.SetNode('a')
		self.assert_(n.GetNameInParent() == 'a')

	def testSetVertex(self):
		s = self.storage
		r = s.root
		self.failUnlessRaises(e4py.error, r.SetVertex, 'a', 1)
		populateNode(r, {'a': 1})
		r.SetVertex('a', 'str')
		self.assert_(r['a'] == 'str')
		self.failUnlessRaises(e4py.error, r.SetVertex, 2, 1)
		r.SetVertex(1, 1.2)
		self.assert_(r[1] == 1.2)

	def testAddVertex(self):
		s = self.storage
		r = s.root
		r.AddVertex('a', e4py.E4_IOLAST, 0, 1)
		self.failUnless(r.VertexCount() == 1)

	def testAddVertexRef(self):
		s = self.storage
		r = s.root
		v, rank = r.AddVertexRef('a', e4py.E4_IOLAST, 0, 1)
		self.failUnless(v.value == 1 and rank == 1)

	def testAddNode(self):
		s = self.storage
		r = s.root
		n, rank = r.AddNode('a', e4py.E4_IOLAST, 0)
		self.failUnless(n.GetNameInParent() == 'a')

	def testMoveVertex(self):
		s = self.storage
		r = s.root
		populateNode(r, {'a': 1, 'b': {}})
		a = r.GetVertexRef('a')
		b = r['b']		#node
		b.MoveVertex(a, e4py.E4_IOLAST, 0)
		self.failUnless(r.VertexCount() == 1 and b.VertexCount() == 1)
		
	def testGetVertex(self):
		s = self.storage
		r = s.root
		populateNode(r, {'a': 1})
		a = r.GetVertex('a')
		self.failUnless(a == 1)

	def testDetachVertex(self):
		s = self.storage
		r = s.root
		populateNode(r, {'a': 1})
		a = r.GetVertexRef('a')
		self.failIf(a.isDetached)
		r.DetachVertex('a')
		self.failUnless(a.isDetached)

	def testGetVertexRef(self):
		s = self.storage
		r = s.root
		populateNode(r, {'a': 1})
		a = r.GetVertexRef('a')
		self.failUnless(a.value == 1)

	def testVertexType(self):
		s = self.storage
		r = s.root
		populateNode(r, {'a': 1})
		self.failUnless(r.VertexType(1) == e4py.E4_VTINT)

	def testVertexName(self):
		s = self.storage
		r = s.root
		populateNode(r, {'a': 1})
		self.failUnless(r.VertexName(1) == 'a')

	def testRenameVertex(self):
		s = self.storage
		r = s.root
		populateNode(r, {'a': 1})
		a = r.GetVertexRef('a')
		r.RenameVertex(1, 'b')
		self.failUnless(a.name == 'b')

	def testVertexRank(self):
		s = self.storage
		r = s.root
		populateNode(r, {'a': 1})
		self.failUnless(r.VertexRank('a') == 1)

	def testExists(self):
		s = self.storage
		r = s.root
		populateNode(r, {'a': 1})
		self.failUnless(r.Exists('a'))

	def testGetParent(self):
		s = self.storage
		r = s.root
		populateNode(r, {'a': {}})
		a = r['a']
		self.failUnless(a.GetParent() == r)
		
	def testParentCount(self):
		s = self.storage
		r = s.root
		populateNode(r, {'a': {}})
		a = r['a']
		self.failUnless(a.ParentCount() == 1)

	def testOccurrenceCount(self):
		s = self.storage
		r = s.root
		populateNode(r, {'a': {}})
		a = r['a']
		self.failUnless(a.ParentCount() == 1)

	def testParentRank(self):
		s = self.storage
		r = s.root
		populateNode(r, {'a': 1, 'b': {'c': {}}})
		b = r['b']
		c = r['b']['c']
		self.failUnless(c.ParentRank(b) == 1)

	def testGetRankInParent(self):
		s = self.storage
		r = s.root
		populateNode(r, {'a': 1, 'b': {}})
		b = r['b']
		self.failUnless(b.GetRankInParent() == 2)

	def testGetNameInParent(self):
		s = self.storage
		r = s.root
		populateNode(r, {'a': 1, 'b': {}})
		b = r['b']
		self.failUnless(b.GetNameInParent() == 'b')

	def testVertexUserData(self):
		s = self.storage
		r = s.root
		populateNode(r, {'a': 1})
		r.SetVertexUserData('a', 2)
		self.failUnless(r.GetVertexUserData('a') == 2)

	def testGetVertexRefFromParent(self):
		pass

	def testisRoot(self):
		s = self.storage
		r = s.root
		self.failUnless(r.isRoot)

	def testisDetached(self):
		s = self.storage
		r = s.root
		a = s.CreateDetachedNode()
		self.failUnless(a.isDetached)
		r.AddVertex('a', e4py.E4_IOLAST, 0, a)
		self.failIf(a.isDetached)

	def teststorage(self):
		s = self.storage
		r = s.root
		self.failUnless(r.storage == s)

	def testroot(self):
		s = self.storage
		r = s.root
		self.failUnless(r.root == r)

	def testuid(self):
		s = self.storage
		r = s.root
		self.failUnless(r.uid != 0)

	def testuserData(self):
		s = self.storage
		r = s.root
		r.userData = 1
		self.failUnless(r.userData == 1)

	def testkind(self):
		s = self.storage
		r = s.root
		self.failUnless(r.kind == e4py.E4_RKNODE)

	def testvalid(self):
		s = self.storage
		r = s.root
		self.failUnless(r.valid)

	def testtempUID(self):
		s = self.storage
		r = s.root
		self.failUnless(r.tempUID != 0)

	def testtransientUserData(self):
		s = self.storage
		r = s.root
		r.transientUserData = 1
		self.failUnless(r.transientUserData == 1)

	def tearDown(self):
		try:		#delete storage, ignore if none exists
			self.storage.Delete()
		except:
			pass
		self.storage = None


def makeTestSuite():
	classes = (NodeTest, )
	suites = []
	for c in classes:
		suites.append(unittest.makeSuite(c,'test'))
	return unittest.TestSuite(suites)


if __name__=='__main__':
	runner = unittest.TextTestRunner(stream=sys.stdout)
	unittest.main(defaultTest='makeTestSuite', testRunner=runner)

