#!/usr/bin/env python
import eaSDIF

print("eaSDIF version:",eaSDIF.Version())

def _get_matrix_value(m, r, c):
    return 1 + 10 * (m - 1) + c + (r + 1) * .125

def _fill_matrix(m, omt):
    omt.Init(eaSDIF.CreateSignature('1','M','A','T'), m*2, 3, eaSDIF.eFloat4)
    for r in range(m * 2):
        for c in range(3):
          omt.Set(r, c, _get_matrix_value(m, r, c))

out = eaSDIF.Entity()
nvt = eaSDIF.NameValueTable()
nvt.AddNameValue('name0','value0')
nvt.AddNameValue('name1','value1')
nvt.AddNameValue('name2','value2')
out.AddNVT(nvt)
mt = eaSDIF.MatrixType(eaSDIF.CreateSignature('1','M','A','T'))
mt.AddColumn('col0')
mt.AddColumn('col1')
mt.AddColumn('col2')
out.AddMatrixType(mt)
ft = eaSDIF.FrameType(eaSDIF.CreateSignature('1','F','R','M'))
ft.AddMatrixType(mt,'test_matrix')
out.AddFrameType(ft)
ofr = eaSDIF.Frame()
ofr.SetHeader(eaSDIF.CreateSignature('1','F','R','M'), 0, 0.25)
omt = eaSDIF.Matrix()
_fill_matrix(1, omt)
ofr.AddMatrix(omt)
out.OpenWrite("test.sdif")
ofr.Write(out)
ofr.ClearData()
_fill_matrix(2,omt)
ofr.SetHeader(eaSDIF.CreateSignature('1','F','R','M'), 1, .5)
ofr.AddMatrix(omt)
ofr.Write(out)
out.Close();

ine = eaSDIF.Entity()
ine.OpenRead('test.sdif')
invt = ine.GetNVT(0)
if invt.GetNbNameValue() != 3:
    raise RuntimeError("wrong size of NVT {0}: ".format(invt.GetNbNameValue()))
if invt.GetValue('name0') != 'value0':
    raise RuntimeError("wrong value for name0: {0}".format(invt.GetValue('name0')))
if invt.GetValue('name1') != 'value1':
    raise RuntimeError("wrong value for name1: {0}".format(invt.GetValue('name1')))
if invt.GetValue('name2') != 'value2':
    raise RuntimeError("wrong value for name2: {0}".format(invt.GetValue('name2')))
ftv = eaSDIF.FrameTypeVector()
ine.GetTypes(ftv)
if len(ftv) != 1:
    raise RuntimeError("wrong number of frame types: {0}".format(len(ftv)))
ift = ftv[0]
if ift.GetSignature() != '1FRM':
    raise RuntimeError("wrong frame signature: {0}".format(ift.GetSignature()))
if ift.GetNbMatrices() != 1:
    raise RuntimeError("wrong number of matrix types in frame: {0}".format(ift.GetNbMatrices()))
if ift.mvMatrixNames[0] != 'test_matrix':
    raise RuntimeError("wrong matrix name in frame: {0}".format(ift.mvMatrixNames[0]))
# the matrix columns within a frame are not filled by SDIFEntity::GetTypes and
# so cannot be checked
if ift.mvMatrixTypes[0].GetSignature() != '1MAT':
    raise RuntimeError("wrong matrix signature in frame: {0}".format(ift.mvMatrixTypes[0].GetSignature()))
mtv = eaSDIF.MatrixTypeVector()
ine.GetTypes(mtv)
if len(mtv) != 1:
    raise RuntimeError("wrong number of matrix types: {0}".format(len(mtv)))
imt = mtv[0]
if imt.GetSignature() != '1MAT':
    raise RuntimeError("wrong matrix signature: {0}".format(imt.GetSignature()))
if imt.GetNbCols() != 3:
    raise RuntimeError("wrong number of columns in matrix {0}".format(imt.GetNbCols()))
if imt.mvColumnNames[0] != 'col0':
    raise RuntimeError("wrong name for column 0: {0}".format(imt.mvColumnNames[0]))
if imt.mvColumnNames[1] != 'col1':
    raise RuntimeError("wrong name for column 1: {0}".format(imt.mvColumnNames[1]))
if imt.mvColumnNames[2] != 'col2':
    raise RuntimeError("wrong name for column 2: {0}".format(imt.mvColumnNames[2]))
ifr = eaSDIF.Frame()
ima = eaSDIF.Matrix()
m = 1
while not ine.eof():
    if not ine.ReadNextFrame(ifr):
        raise RuntimeError("error reading frame") 
    if ifr.GetSignature() != '1FRM':
        raise RuntimeError("wrong frame signature: {0}".format(ifr.GetSignature()))
    if ifr.GetStreamID() != m - 1:
        raise RuntimeError("wrong stream : {0}".format(ifr.GetStreamID()))
    if ifr.GetTime() != m * .25:
        raise RuntimeError("wrong time : {0}".format(ifr.GetTime()))
    if ifr.GetNbMatrix() != 1:
        raise RuntimeError("wrong number of matrices: {0}".format(ifr.GetNbMatrix()))
    ima = ifr.GetMatrix(0)
    if ima.GetSignature() != '1MAT':
        raise RuntimeError("wrong matrix signature: {0}".format(ima.GetSignature()))
    if ima.GetNbCols() != 3:
        raise RuntimeError("wrong number of columns : {0}".format(ima.GetNbCols()))
    if ima.GetNbRows() != m * 2:
        raise RuntimeError("wrong number of rows : {0}".format(ima.GetNbRows()))
    for r in range(m * 2):
        for c in range(3):
            v = ima.GetFloat(r, c)
            e = _get_matrix_value(m, r, c)
            if v != e:
                raise RuntimeError("wrong value at {0}, {1}: {2}, expected {3}".format(r,c,v,e))
    m = m + 1
ine.Close()
print("all tests passed!")

