// SpaFEDTe, a Template based C++ library for creating 
// Discontinuous Finite Element Spaces,
// Copyright (C) 2012 Lorenzo Alessio Botti

/* This library is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU Lesser General Public */ 
/* License as published by the Free Software Foundation either */ 
/* version 3.0 of the License, or (at your option) any later version. */

/* This software is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU */
/* Lesser General Public License for more details. */

/* You should have received a copy of the GNU Lesser General Public */
/* License along with this software; if not, a copy of the full */
/* GNU Lesser General Public License can be found at */
/* http://www.gnu.org/licenses/. */

// This implementation is mostly borrowed from MOAB readers

#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <sstream>

#include "ReadMeshVtu.hpp"
#include "VtuMeshUtil.hpp"
#include "FELib.hpp"

#include "Mesh.hpp"

ReadMeshVtu::ReadMeshVtu()
    : mPartitionTagName("PARALLEL_PARTITION")
{
}

ReadMeshVtu::~ReadMeshVtu()
{
}


//ErrorCode ReadMeshVtu::check_pvtu_file(const char * filename, Mesh& mesh)
//{
//  ErrorCode result;
//  std::vector<Range> element_list;
//  Range vertices;
//  rapidxml::file<> fileToRead(filename);
//  rapidxml::xml_document<> doc;    
//  doc.parse<rapidxml::parse_trim_whitespace|rapidxml::parse_validate_closing_tags>(fileToRead.data());    
//
//  const rapidxml::xml_node<>* vtkFile = doc.first_node();
//  if (!vtkFile)
//    MB_SET_ERR(MB_FAILURE, "VtuReader error: no xml nodes in file "<<filename);
//  // Check header
//  if (strcmp(vtkFile->name(),"VTKFile") != 0)
//    MB_SET_ERR(MB_FAILURE, "VtuReader error in file "<<filename<<": not reading a VTKFile. First node is "<<vtkFile->name());
//  if (!vtkFile->first_attribute("type"))
//    MB_SET_ERR(MB_FAILURE,"VtuReader error: no VTK file type in file "<<filename);
//  if (strcmp(vtkFile->first_attribute("type")->value(),"PUnstructuredGrid") != 0)
//    MB_SET_ERR(MB_FAILURE,"VtuReader error: not reading a punstructured grid. File type is "<<vtkFile->first_attribute("type")->value());
//  if (vtkFile->first_attribute("version"))
//  {
//    if (strcmp(vtkFile->first_attribute("version")->value(),"0.1") != 0)
//      MB_SET_ERR(MB_FAILURE,"VtuReader error: version mismatch. Version is "<<vtkFile->first_attribute("version")->value());
//  }
// 
//  // Verify nodes coordinates attribute
//  const rapidxml::xml_node<>* grid=vtkFile->first_node("PUnstructuredGrid");
//  if (!grid)
//    MB_SET_ERR(MB_FAILURE,"VtuReader error: no PUnstructuredGrid in VTKfile "<<filename);
//  if (!grid->first_node("PPoints"))
//    MB_SET_ERR(MB_FAILURE,"VtuReader error: no PPoints node in VTKfile "<<filename);
//  if (!grid->first_node("PPoints")->first_node("PDataArray"))
//    MB_SET_ERR(MB_FAILURE,"VtuReader error: no PPoints PDataArray in VTKfile "<<filename);
//  if (!grid->first_node("PPoints")->first_node("PDataArray")->first_attribute("type"))
//    MB_SET_ERR(MB_FAILURE,"VtuReader error: no PPoint PDataArray data type, aborting.");
//  const char * dataType = grid->first_node("PPoints")->first_node("PDataArray")->first_attribute("type")->value();
//  if (!VtuMeshUtil::check_vtu_data_type(dataType,"Float")) 
//    MB_SET_ERR(MB_FAILURE,"VtuReader error: wrong PPoint PDataArray coordinates data type "<<dataType);
//  if (!grid->first_node("PPoints")->first_node("PDataArray")->first_attribute("NumberOfComponents"))
//    MB_SET_ERR(MB_FAILURE,"VtuReader error: no number of components info in PPoints for VTKfile "<<filename);
//  if (atol(grid->first_node("PPoints")->first_node("PDataArray")->first_attribute("NumberOfComponents")->value()) != 3)
//    MB_SET_ERR(MB_FAILURE,"VtuReader error: wrong number of point coordinates "
//             <<grid->first_node("PPoints")->first_node("PDataArray")->first_attribute("NumberOfComponents")->value());
//
//  // Verify nodes global ids attribute
//  const rapidxml::xml_node<>* pointAttributes = grid->first_node("PPointData"); 
//  bool nodeGlobalIds = false;
//  if (pointAttributes)
//  {
//    for(rapidxml::xml_node<> *pDataArray=pointAttributes->first_node("PDataArray"); pDataArray; pDataArray=pDataArray->next_sibling("PDataArray"))
//    {
//      if (!pDataArray->first_attribute("Name"))
//        MB_SET_ERR(MB_FAILURE,"VtuReader error: missing name for PPointData PDataArray");
//      if (strcmp(pDataArray->first_attribute("Name")->value(), "GLOBAL_ID") == 0)
//      {
//        nodeGlobalIds = true;
//        if (atoi(pDataArray->first_attribute("NumberOfComponents")->value()) != 1)
//          MB_SET_ERR(MB_FAILURE,"VtuReader error: one global id per node, got "
//                   <<atoi(pDataArray->first_attribute("NumberOfComponents")->value()));
//      }
//    }
//  }
//  if (!nodeGlobalIds)
//    MB_SET_ERR(MB_FAILURE,"VtuReader error: input file does not contain nodes global ids");
//  
//  // Verify cell global ids and parallel_partition attributes
//  const rapidxml::xml_node<>* cellAttributes = grid->first_node("PCellData"); 
//  bool cellGlobalIds = false;
//  bool parallelPartition = false;
//  if (cellAttributes)
//  {
//    for(rapidxml::xml_node<> *pDataArray=cellAttributes->first_node("PDataArray"); pDataArray; pDataArray=pDataArray->next_sibling("PDataArray"))
//    {
//      if (!pDataArray->first_attribute("Name"))
//        MB_SET_ERR(MB_FAILURE,"VtuReader error: missing name for PCellData PDataArray");
//      if (strcmp(pDataArray->first_attribute("Name")->value(), "GLOBAL_ID") == 0)
//      {
//        cellGlobalIds = true;
//        if (atoi(pDataArray->first_attribute("NumberOfComponents")->value()) != 1)
//          MB_SET_ERR(MB_FAILURE,"VtuReader error: one global id per node, got "
//                   <<atoi(pDataArray->first_attribute("NumberOfComponents")->value()));
//      }
//      if (strcmp(pDataArray->first_attribute("Name")->value(), "PARALLEL_PARTITION") == 0)
//      {
//        parallelPartition = true;
//        if (atoi(pDataArray->first_attribute("NumberOfComponents")->value()) != 1)
//          MB_SET_ERR(MB_FAILURE,"VtuReader error: one partition id per cell, got "
//                   <<atoi(pDataArray->first_attribute("NumberOfComponents")->value()));
//      }
//    }
//  }
//  if (!cellGlobalIds)
//    MB_SET_ERR(MB_FAILURE,"VtuReader error: input file does not contain cell global ids");
//  if (!parallelPartition)
//    MB_SET_ERR(MB_FAILURE,"VtuReader error: input file does not contain partition ids");
//  
//  // Verify number of partition files and number of processors consistency
//  // Verify partition file names
//  std::string fileNameString = std::string(filename);
//  int sindex = fileNameString.find_last_of("/"); 
//  if (sindex < fileNameString.size())
//    fileNameString = fileNameString.substr(sindex+1); 
//  int dotindex = fileNameString.find_last_of("."); 
//  fileNameString = fileNameString.substr(0,dotindex); 
//  unsigned int nPieces = 0;
//  for(rapidxml::xml_node<> *piece=grid->first_node("Piece"); piece; piece=piece->next_sibling("Piece"))
//  {
//    char number[8];
//    sprintf(number,"_%02d",nPieces);
//    if (!piece->first_attribute("Source"))
//      MB_SET_ERR(MB_FAILURE,"VtuReader error: missing source for Piece "<<nPieces);
//    std::string pieceSource = piece->first_attribute("Source")->value();
//    int pindex = pieceSource.find_last_of("/");
//    if (pindex < pieceSource.size())
//      pieceSource = pieceSource.substr(pindex+1);
//    if (pieceSource.find(fileNameString) != 0)
//      MB_SET_ERR(MB_FAILURE,"Partition files names do not match convention");
//    if (pieceSource.find(number) != fileNameString.size())
//      MB_SET_ERR(MB_FAILURE,"Partition files names do not match convention");
//    nPieces++;
//  }
//  if (nPieces != FELib::n_processors())
//    MB_SET_ERR(MB_FAILURE,"VtuReader error: number of partitions and number of processors do not match");
//  return MB_SUCCESS;
//}


                          
