END_TEST


START_TEST (test_SpatialExtension_read_L3V1V1_defaultNS)
{
    string file = TestDataDirectory;
    file += "/read_L3V1V1_defaultNS.xml";

    SBMLDocument *document = readSBMLFromFile(file.c_str());
    string sbmlDoc = writeSBMLToStdString(document);
    Model *model = document->getModel();

    //document->printErrors();

    fail_unless(model != NULL);
    //fail_unless(document->getNumErrors() == 0);

    // model : compartment
    fail_unless(model->getNumCompartments() == 1);

    Compartment *comp = model->getCompartment(0);

    // compartment : compartmentMapping
    SpatialCompartmentPlugin* cplugin = static_cast<SpatialCompartmentPlugin*>(comp->getPlugin("spatial"));
    fail_unless(cplugin != NULL);

    CompartmentMapping *cMapping = cplugin->getCompartmentMapping();
    if (cMapping->isSetId()) {
        fail_unless(cMapping->getId()		 == "compMap1");
        fail_unless(cMapping->getDomainType()	 == "dtype1");
        fail_unless(cMapping->getUnitSize()		 == 1);
    }

    // model : species 1
    fail_unless(model->getNumSpecies() == 2);

    Species *sp = model->getSpecies(0);

    SpatialSpeciesPlugin* srplugin = static_cast<SpatialSpeciesPlugin*>(sp->getPlugin("spatial"));
    fail_unless(srplugin != NULL);
    fail_unless(srplugin->getIsSpatial() == true);

    // model : species 2
    sp = model->getSpecies(1);
    srplugin = static_cast<SpatialSpeciesPlugin*>(sp->getPlugin("spatial"));
    fail_unless(srplugin != NULL);
    fail_unless(srplugin->getIsSpatial() == true);

    // model : parameters (species diffusion, advection coeffs, species boundary conditions, coordinate components from Geometry
    fail_unless(model->getNumParameters() == 5);



    // parameter 0 : diffusionCoefficient
    Parameter *param = model->getParameter(0);
    SpatialParameterPlugin* pplugin = static_cast<SpatialParameterPlugin*>(param->getPlugin("spatial"));
    fail_unless(pplugin != NULL);
    fail_unless(pplugin->isSpatialParameter() == true);
    fail_unless(pplugin->getType() == SBML_SPATIAL_DIFFUSIONCOEFFICIENT);
    DiffusionCoefficient *diffCoeff = pplugin->getDiffusionCoefficient();
    fail_unless(diffCoeff->getVariable()		== "ATPc");
    fail_unless(diffCoeff->isSetCoordinateReference1());
    fail_unless(diffCoeff->getCoordinateReference1() == SPATIAL_COORDINATEKIND_CARTESIAN_X);

    // parameter 1 : advectionCoefficient
    param = model->getParameter(1);
    pplugin = static_cast<SpatialParameterPlugin*>(param->getPlugin("spatial"));
    fail_unless(pplugin != NULL);
    fail_unless(pplugin->isSpatialParameter() == true);
    fail_unless(pplugin->getType() == SBML_SPATIAL_ADVECTIONCOEFFICIENT);
    AdvectionCoefficient *advCoeff = pplugin->getAdvectionCoefficient();
    fail_unless(advCoeff->getVariable()		== "ATPc");
    fail_unless(advCoeff->getCoordinate() == SPATIAL_COORDINATEKIND_CARTESIAN_X);

    // parameter 2 : boundaryCondition X
    param = model->getParameter(2);
    pplugin = static_cast<SpatialParameterPlugin*>(param->getPlugin("spatial"));
    fail_unless(pplugin != NULL);
    fail_unless(pplugin->isSpatialParameter() == true);
    fail_unless(pplugin->getType() == SBML_SPATIAL_BOUNDARYCONDITION);
    BoundaryCondition *bc = pplugin->getBoundaryCondition();
    fail_unless(bc->getVariable()		   == "ATPc");
    fail_unless(bc->getCoordinateBoundary() == "Xmin");
    fail_unless(bc->getType() == SPATIAL_BOUNDARYKIND_DIRICHLET);

    // parameter 3 : SpatialSymbolReference (coordinateComponent from geometry)
    param = model->getParameter(3);
    pplugin = static_cast<SpatialParameterPlugin*>(param->getPlugin("spatial"));
    fail_unless(pplugin != NULL);
    SpatialSymbolReference *spSymRef = pplugin->getSpatialSymbolReference();
    fail_unless(spSymRef->getSpatialRef() == "coordComp1");

    // model : reaction
    fail_unless(model->getNumReactions() == 1);

    Reaction *rxn = model->getReaction(0);
    SpatialReactionPlugin* rplugin = static_cast<SpatialReactionPlugin*>(rxn->getPlugin("spatial"));
    fail_unless(rplugin != NULL);
    fail_unless(rplugin->getIsLocal() == true);

    // get the Geometry
    SpatialModelPlugin* mplugin = static_cast<SpatialModelPlugin*>(model->getPlugin("spatial"));
    fail_unless(mplugin != NULL);

    Geometry *geometry = mplugin->getGeometry();
    fail_unless(geometry != NULL);
    fail_unless(geometry->getPackageName()		== "spatial");
    fail_unless(geometry->getCoordinateSystem()	== SPATIAL_GEOMETRYKIND_CARTESIAN);

    // geometry coordinateComponent
    fail_unless(geometry->getNumCoordinateComponents() == 1);
    fail_unless(geometry->getListOfCoordinateComponents()->getPackageName() == "spatial");

    CoordinateComponent* coordComp = geometry->getCoordinateComponent(0);
    fail_unless(coordComp->getId()        == "coordComp1");
    fail_unless(coordComp->getType()	== SPATIAL_COORDINATEKIND_CARTESIAN_X);
    fail_unless(coordComp->getUnit()			== "umeter");
    fail_unless(coordComp->getPackageName()		== "spatial");

    // boundaryMin and boundayMax within coordinateComponent
    Boundary *minX = coordComp->getBoundaryMin();
    fail_unless(minX->getId()	  == "Xmin");
    fail_unless(minX->getValue()		  == 0);
    fail_unless(minX->getPackageName() == "spatial");

    Boundary *maxX = coordComp->getBoundaryMax();
    fail_unless(maxX->getId()   == "Xmax");
    fail_unless(maxX->getValue()		  == 10);
    fail_unless(maxX->getPackageName() == "spatial");

    // geometry domainType
    fail_unless(geometry->getNumDomainTypes() == 1);
    fail_unless(geometry->getListOfDomainTypes()->getPackageName() == "spatial");

    DomainType *domainType = geometry->getDomainType(0);
    fail_unless(domainType->getId()         == "dtype1");
    fail_unless(domainType->getSpatialDimensions() == 3);
    fail_unless(domainType->getPackageName()		  == "spatial");

    // geometry domains
    fail_unless(geometry->getNumDomains() == 2);
    fail_unless(geometry->getListOfDomains()->getPackageName() == "spatial");

    Domain* domain = geometry->getDomain(0);
    fail_unless(domain->getId()   == "domain1");
    fail_unless(domain->getDomainType() == "dtype1");
    //fail_unless(domain->getImplicit()    == false);
    //fail_unless(domain->getShapeId()     == "circle");
    fail_unless(domain->getPackageName() == "spatial");

    // interiorPoints in Domain
    fail_unless(domain->getNumInteriorPoints() == 1);
    fail_unless(domain->getListOfInteriorPoints()->getPackageName() == "spatial");

    InteriorPoint* interiorPt = domain->getInteriorPoint(0);
    fail_unless(interiorPt->getCoord1()		== 1);
    fail_unless(interiorPt->getPackageName() == "spatial");

    // second domain in geometry
    domain = geometry->getDomain(1);
    fail_unless(domain->getId()   == "domain2");
    fail_unless(domain->getDomainType() == "dtype1");
    //fail_unless(domain->getImplicit()    == false);
    //fail_unless(domain->getShapeId()     == "square");
    fail_unless(domain->getPackageName() == "spatial");

    // Domain : interiorPoints
    fail_unless(domain->getNumInteriorPoints() == 1);
    fail_unless(domain->getListOfInteriorPoints()->getPackageName() == "spatial");

    interiorPt = domain->getInteriorPoint(0);
    fail_unless(interiorPt->getCoord1()		== 5);
    fail_unless(interiorPt->getPackageName() == "spatial");

    // geometry adjacentDomains
    fail_unless(geometry->getNumAdjacentDomains() == 1);
    fail_unless(geometry->getListOfAdjacentDomains()->getPackageName() == "spatial");

    AdjacentDomains* adjDomain = geometry->getAdjacentDomains(0);
    fail_unless(adjDomain->getId()   == "adjDomain1");
    fail_unless(adjDomain->getDomain1()     == "domain1");
    fail_unless(adjDomain->getDomain2()     == "domain2");
    fail_unless(adjDomain->getPackageName() == "spatial");

    // geometry : geometryDefinitions
    fail_unless(geometry->getNumGeometryDefinitions() == 2);
    fail_unless(geometry->getListOfGeometryDefinitions()->getPackageName() == "spatial");

    GeometryDefinition *gd = geometry->getGeometryDefinition(0);
    AnalyticGeometry *analyticGeom = static_cast<AnalyticGeometry*>(gd);
    fail_unless(analyticGeom->getId()   == "analyticGeom1");
    fail_unless(analyticGeom->getPackageName() == "spatial");

    // AnalyticGeometry : analyticVolumes
    fail_unless(analyticGeom->getNumAnalyticVolumes() == 1);
    fail_unless(analyticGeom->getListOfAnalyticVolumes()->getPackageName() == "spatial");

    AnalyticVolume* av = analyticGeom->getAnalyticVolume(0);
    fail_unless(av->getId()    == "analyticVol1");
    fail_unless(av->getDomainType()   == "dtype1");
    fail_unless(av->getFunctionType() == SPATIAL_FUNCTIONKIND_LAYERED);
    fail_unless(av->getOrdinal()      == 1);
    fail_unless(av->getPackageName()  == "spatial");
    // ??????Math????

    // geometry : sampledFieldGeometry
    gd = geometry->getGeometryDefinition(1);
    SampledFieldGeometry* sfGeom = static_cast<SampledFieldGeometry*>(gd);
    fail_unless(sfGeom->getId()   == "sampledFieldGeom1");
    fail_unless(sfGeom->getPackageName() == "spatial");

    // sampledFieldGeometry : SampledVolumes
    fail_unless(sfGeom->getNumSampledVolumes() == 1);
    fail_unless(sfGeom->getListOfSampledVolumes()->getPackageName() == "spatial");

    SampledVolume* sv = sfGeom->getSampledVolume(0);
    fail_unless(sv->getId()    == "sv_1");
    fail_unless(sv->getDomainType()   == "dtype1");
    fail_unless(sv->getSampledValue() == 128);
    fail_unless(sv->getMinValue()     == 0);
    fail_unless(sv->getMaxValue()     == 255);
    fail_unless(sv->getPackageName()  == "spatial");

    // sampledFieldGeometry : SampledField
    SampledField* sf = geometry->getSampledField( sfGeom->getSampledField() );
    fail_unless(sf->getId()		  == "sampledField1");
    fail_unless(sf->getDataType()		  == SPATIAL_DATAKIND_UINT8);
    fail_unless(sf->getInterpolationType() == SPATIAL_INTERPOLATIONKIND_LINEAR);
    fail_unless(sf->getCompression()          == SPATIAL_COMPRESSIONKIND_UNCOMPRESSED);
    fail_unless(sf->getNumSamples1()       == 4);
    fail_unless(sf->getNumSamples2()       == 4);
    fail_unless(sf->getNumSamples3()       == 2);
    fail_unless(sf->getPackageName()		  == "spatial");

    // sampledField : ImageData
    fail_unless(sf->getSamplesLength()  == 32);
    int* samples = new int[sf->getSamplesLength()];
    sf->getSamples(samples);
    fail_unless(samples[0] == 0);

    string s2 = writeSBMLToStdString(document);

    fail_unless(sbmlDoc==s2);

    delete document;
    delete[] samples;
}