//=============================================================================
//
//  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/simulation/windtunnel/Registrar.h"

#include "smtk/simulation/windtunnel/Metadata.h"

// SMTK includes
#include "smtk/attribute/Attribute.h"
#include "smtk/attribute/FileItem.h"
#include "smtk/attribute/IntItem.h"
#include "smtk/attribute/StringItem.h"
#include "smtk/io/Logger.h"
#include "smtk/operation/Manager.h"
#include "smtk/operation/Operation.h"
#include "smtk/project/Manager.h"

#include <boost/filesystem.hpp>

#include <cassert>
#include <iostream>
#include <string>
#include <vector>

namespace
{
// Python operations
const std::vector<std::string> OperationFiles{
  std::string("create_project.py"), std::string("blockmesh.py"),     std::string("import_model.py"),
  std::string("surfaceextract.py"), std::string("snappyhexmesh.py"), std::string("refinemesh.py"),
  std::string("icofoam.py"),        std::string("simplefoam.py"),    std::string("setup_paths.py")
};

const int OP_SUCCEEDED = static_cast<int>(smtk::operation::Operation::Outcome::SUCCEEDED);
} // namespace

namespace smtk
{
namespace simulation
{
namespace windtunnel
{
std::vector<std::string> Registrar::s_pythonOperationNames;

void Registrar::registerTo(const smtk::project::Manager::Ptr& projectManager)
{
  bool registered = projectManager->registerProject(Metadata::PROJECT_TYPE);
  if (!registered)
  {
    std::cout << "WindTunnel operations already registered. " << __FILE__ << ":" << __LINE__
              << std::endl;
    return;
  }

  // Register python operations
  if (Metadata::OPERATIONS_DIRECTORY.empty())
  {
    smtkErrorMacro(
      smtk::io::Logger::instance(),
      "Cannot import python operations: OPERATIONS_DIRECTORY unknown");
    return;
  }
  boost::filesystem::path opsDirectory(Metadata::OPERATIONS_DIRECTORY);

  auto opManager = projectManager->operationManager();
  auto importOp = opManager->create("smtk::operation::ImportPythonOperation");
  for (const std::string& opFilename : OperationFiles)
  {
    boost::filesystem::path opPath = opsDirectory / opFilename;
    importOp->parameters()->findFile("filename")->setValue(opPath.string());
    auto result = importOp->operate();
    int outcome = result->findInt("outcome")->value();
    if (outcome != OP_SUCCEEDED)
    {
      smtkInfoMacro(smtk::io::Logger::instance(), importOp->log().convertToString());
      smtkErrorMacro(
        smtk::io::Logger::instance(), "Error importing " << opFilename << ": outcome " << outcome);
    }

    std::string opName = result->findString("unique_name")->value();
    s_pythonOperationNames.push_back(opName);
  }
}

void Registrar::unregisterFrom(const smtk::project::Manager::Ptr& projectManager)
{
  projectManager->unregisterProject(Metadata::PROJECT_TYPE);

  auto opManager = projectManager->operationManager();
  for (const std::string& opName : s_pythonOperationNames)
  {
    if (opManager->registered(opName))
    {
      opManager->unregisterOperation(opName);
    }
  }
  s_pythonOperationNames.clear();
}

} // namespace windtunnel
} // namespace simulation
} // namespace smtk
