from simbios.simtk import Vec3, Row3
import simbios.simtk as simtk
import unittest

class TestVec3(unittest.TestCase):
    def test_addition(self):
        v1 = Vec3(1,2,3)
        v2 = Vec3(2,3,4)
        v3 = v1 + v2
        self.assertEqual(v3[0], 3)
        self.assertEqual(v3[1], 5)
        self.assertEqual(v3[2], 7)
        self.assertEqual(v3, Vec3(3,5,7))
        self.assertNotEqual(v3, Vec3(2,5,7))
        # subtraction
        self.assertEqual(v2 - v1, Vec3(1,1,1))
        v3 += Vec3(1,1,1)
        self.assertEqual(v3, Vec3(4,6,8))
        v3 -= Vec3(2,2,2)
        self.assertEqual(v3, Vec3(2,4,6))
        
    def test_member_functions(self):
        v1 = Vec3(1,4,0)
        self.assertEqual(v1.size(), 3)
        self.assertEqual(len(v1), 3)
        self.assertEqual(v1.nrow(), 3)
        self.assertEqual(v1.ncol(), 1)
        self.assertEqual(v1.scalarNormSqr(), 17.0)
        self.assertEqual(v1.sqrt(), Vec3(1,2,0))
        
    def test_equality(self):
        v1 = Vec3(1,2,3)
        v2 = Vec3(1,2,4)
        v3 = Vec3(1,2,4)
        self.assertEqual(v1, v1)
        self.assertEqual(v2, v2)
        self.assertNotEqual(v1, v2)
        self.assertNotEqual(v2, v1)
        self.assertEqual(v2, v3)
        self.assertEqual(v3, v2)
        self.assertTrue(v1 == v1)
        self.assertTrue(v2 == v2)
        self.assertTrue(v3 == v2)
        self.assertFalse(v1 == v2)
        self.assertFalse(v1 != v1)
        self.assertFalse(v2 != v3)
        # Vec3/tuple equality
        self.assertEqual(Vec3(1,2,3), (1,2,3))
        # Only works for Vec3, not NegVec3...
        # self.assertEqual(-Vec3(1,2,3), (-1,-2,-3))
    
    def test_indexing(self):
        # slices
        self.assertEqual([1,2,3][:], [1,2,3])
        self.assertEqual((1,2,3)[:], (1,2,3))
        self.assertEqual(Vec3(1,2,3)[:], [1,2,3])
        # in range indexes
        self.assertEqual(Vec3(1,2,3)[0], 1.0)
        self.assertEqual(Vec3(1,2,3)[1], 2.0)
        self.assertEqual(Vec3(1,2,3)[2], 3.0)
        self.assertEqual(Vec3(1,2,3)[-3], 1.0)
        self.assertEqual(Vec3(1,2,3)[-2], 2.0)
        self.assertEqual(Vec3(1,2,3)[-1], 3.0)
        # out of range indexes
        self.assertRaises(IndexError, Vec3(1,2,3).__getitem__, 3)
        self.assertRaises(IndexError, Vec3(1,2,3).__getitem__, -4)
        self.assertRaises(IndexError, Vec3(1,2,3).__getitem__, 9999)
        count = 0
        for x in Vec3(1,2,3):
            count += 1
        self.assertEqual(count, 3)
        
    def test_tuple(self):
        v = Vec3(1,2,3)
        # Auto convert tuple to Vec3
        v += (1,1,1)
        self.assertEqual(v, Vec3(2,3,4))
        
    def test_subtraction(self):
        # operator for negative row subtraction is missing
        v1 = Vec3(1,2,3)
        r1 = Row3(1,2,3)
        v1 + v1
        v1 - v1
        (-v1) - v1
        r1 - r1
        r2 = simtk.Row3_3(1,2,3)
        r1 - r2
        (-r1) - r1

    def test_vector_double(self):
        v = simtk.Vector_[float](6)
        self.assertEqual(len(v), 6)

if __name__ == '__main__':
    unittest.main()
