//=========================================================================
//  Copyright (c) Kitware, Inc.
//  All rights reserved.
//  See LICENSE.txt for details.
//
//  This software is distributed WITHOUT ANY WARRANTY; without even
//  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
//  PURPOSE.  See the above copyright notice for more information.
//=========================================================================

#include "smtk/io/mesh/MeshIOMoab.h"
#include "smtk/io/mesh/MeshIO.h"

#include "smtk/mesh/Collection.h"
#include "smtk/mesh/Manager.h"

#include "smtk/mesh/moab/Readers.h"
#include "smtk/mesh/moab/Writers.h"

namespace smtk
{
namespace io
{
namespace mesh
{

MeshIOMoab::MeshIOMoab()
  : MeshIO()
{
  this->Formats.push_back(Format("moab", std::vector<std::string>({ ".h5m", ".mhdf" }),
    Format::Import | Format::Export | Format::Read | Format::Write));
  this->Formats.push_back(
    Format("exodus", std::vector<std::string>({ ".exo", ".exoII", ".exo2", ".g", ".gen" }),
      Format::Import | Format::Export | Format::Read | Format::Write));
  this->Formats.push_back(
    Format("vtk", std::vector<std::string>({ ".vtk" }), Format::Import | Format::Export));
  this->Formats.push_back(
    Format("slac", std::vector<std::string>({ ".slac" }), Format::Import | Format::Export));
  this->Formats.push_back(Format(
    "general mesh viewer", std::vector<std::string>({ ".gmv" }), Format::Import | Format::Export));
  this->Formats.push_back(
    Format("ansys", std::vector<std::string>({ ".ans" }), Format::Import | Format::Export));
  this->Formats.push_back(
    Format("gmsh", std::vector<std::string>({ ".msh", ".gmsh" }), Format::Import | Format::Export));
  this->Formats.push_back(
    Format("stl", std::vector<std::string>({ ".stl" }), Format::Import | Format::Export));
}

smtk::mesh::CollectionPtr MeshIOMoab::importMesh(
  const std::string& filePath, smtk::mesh::ManagerPtr& manager, const std::string&) const
{
  return this->read(filePath, manager, Subset::EntireCollection);
}

bool MeshIOMoab::importMesh(
  const std::string& filePath, smtk::mesh::CollectionPtr collection, const std::string&) const
{
  return this->read(filePath, collection, Subset::EntireCollection);
}

bool MeshIOMoab::exportMesh(const std::string& filePath, smtk::mesh::CollectionPtr collection) const
{
  return this->write(filePath, collection, Subset::EntireCollection);
}

//TODO:
// bool MeshIOMoab::exportMesh( const std::string& filePath,
//                              smtk::mesh::CollectionPtr collection,
//                              smtk::model::ManagerPtr manager,
//                              const std::string& modelPropertyName ) const
// {

// }

smtk::mesh::CollectionPtr MeshIOMoab::read(
  const std::string& filePath, smtk::mesh::ManagerPtr& manager, Subset subset) const
{
  smtk::mesh::CollectionPtr collection;

  switch (subset)
  {
    case Subset::EntireCollection:
      collection = smtk::mesh::moab::read(filePath, manager);
      break;
    case Subset::OnlyDomain:
      collection = smtk::mesh::moab::read_domain(filePath, manager);
      break;
    case Subset::OnlyDirichlet:
      collection = smtk::mesh::moab::read_dirichlet(filePath, manager);
      break;
    case Subset::OnlyNeumann:
      collection = smtk::mesh::moab::read_neumann(filePath, manager);
      break;
    default:
      collection = smtk::mesh::Collection::create();
  }
  return collection;
}

bool MeshIOMoab::read(
  const std::string& filePath, smtk::mesh::CollectionPtr collection, Subset subset) const
{
  bool result;

  switch (subset)
  {
    case Subset::EntireCollection:
      result = smtk::mesh::moab::import(filePath, collection);
      break;
    case Subset::OnlyDomain:
      result = smtk::mesh::moab::import_domain(filePath, collection);
      break;
    case Subset::OnlyDirichlet:
      result = smtk::mesh::moab::import_dirichlet(filePath, collection);
      break;
    case Subset::OnlyNeumann:
      result = smtk::mesh::moab::import_neumann(filePath, collection);
      break;
    default:
      result = false;
  }
  return result;
}

bool MeshIOMoab::write(
  const std::string& filePath, smtk::mesh::CollectionPtr collection, Subset subset) const
{
  switch (subset)
  {
    case Subset::EntireCollection:
      return smtk::mesh::moab::write(filePath, collection);
    case Subset::OnlyDomain:
      return smtk::mesh::moab::write_domain(filePath, collection);
    case Subset::OnlyDirichlet:
      return smtk::mesh::moab::write_dirichlet(filePath, collection);
    case Subset::OnlyNeumann:
      return smtk::mesh::moab::write_neumann(filePath, collection);
    default:
      return false;
  }
}

bool MeshIOMoab::write(smtk::mesh::CollectionPtr collection, Subset subset) const
{
  if (collection->writeLocation().empty())
  { //require a file location
    return false;
  }

  return this->write(collection->writeLocation().absolutePath(), collection, subset);
}
}
}
}
