//=========================================================================
//  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/attribute/Attribute.h"
#include "smtk/attribute/ComponentItem.h"
#include "smtk/attribute/DirectoryItem.h"
#include "smtk/attribute/DoubleItem.h"
#include "smtk/attribute/IntItem.h"
#include "smtk/attribute/ModelEntityItem.h"
#include "smtk/attribute/ResourceItem.h"
#include "smtk/attribute/StringItem.h"

#include "smtk/session/rgg/Assembly.h"
#include "smtk/session/rgg/Core.h"
#include "smtk/session/rgg/Pin.h"
#include "smtk/session/rgg/Registrar.h"
#include "smtk/session/rgg/Resource.h"
#include "smtk/session/rgg/Session.h"

#include "smtk/session/rgg/operators/CreateModel.h"
#include "smtk/session/rgg/operators/EditAssembly.h"
#include "smtk/session/rgg/operators/EditCore.h"
#include "smtk/session/rgg/operators/EditDuct.h"
#include "smtk/session/rgg/operators/EditPin.h"
#include "smtk/session/rgg/operators/ExportInp.h"

#include "smtk/session/rgg/json/jsonAssembly.h"
#include "smtk/session/rgg/json/jsonCore.h"
#include "smtk/session/rgg/json/jsonDuct.h"
#include "smtk/session/rgg/json/jsonPin.h"

#include "smtk/model/EntityRef.h"
#include "smtk/model/Group.h"
#include "smtk/model/Model.h"

#include "TestModel.h"

using namespace smtk::session::rgg;
using json = nlohmann::json;

//force to use filesystem version 3
#define BOOST_FILESYSTEM_VERSION 3
#include <boost/filesystem.hpp>
using namespace boost::filesystem;

namespace
{
std::string dataRoot = DATA_DIR;
std::string writeRoot = SCRATCH_DIR;

void cleanup(const std::string& file_path)
{
  //first verify the file exists
  ::boost::filesystem::path path(file_path);
  if (::boost::filesystem::is_regular_file(path))
  {
    //remove the file_path if it exists.
    ::boost::filesystem::remove(path);
  }
}

int exportAndValidateInpFiles(smtk::model::Model model)
{
  auto exportInpOp = smtk::session::rgg::ExportInp::create();
  if (!exportInpOp)
  {
    std::cerr << "NO \"Export Inp\" operator\n";
    return 1;
  }
  exportInpOp->parameters()->associate(model.component());

  std::string testDirStr = writeRoot + "/" + smtk::common::UUID::random().toString();
  ::boost::filesystem::path testDir(testDirStr);
  bool created = boost::filesystem::create_directory(testDir);
  if (created == false)
  {
    std::cerr << "Could not create temporary directory \"" << testDirStr << "\"\n";
    return 1;
  }

  exportInpOp->parameters()->findDirectory("directory")->setValue(testDirStr);

  auto exportInpOpResult = exportInpOp->operate();

  ::boost::filesystem::remove_all(testDir);

  if (exportInpOpResult->findInt("outcome")->value() !=
      static_cast<int>(smtk::operation::Operation::Outcome::SUCCEEDED))
  {
    std::cerr << "\"Export Inp\" operator failed\n";
    return 1;
  }

  return 0;
}
}

int TestExportInpOp(int argc, char* argv[])
{
  for (int testModelIndex = 0; testModelIndex < 2; ++testModelIndex)
  {
    smtk::model::ResourcePtr resource =
      (testModelIndex == 0 ?
       smtk::session::rgg::test::constructTest11TwoDantModel() :
       smtk::session::rgg::test::constructTestModel());
    smtk::model::Model model =
    resource->entitiesMatchingFlagsAs<smtk::model::EntityRefArray>(smtk::model::MODEL_ENTITY)[0];

    // Create a resource manager
    smtk::resource::Manager::Ptr resourceManager = smtk::resource::Manager::create();

    // Register rgg resources to the resource manager
    {
      smtk::session::rgg::Registrar::registerTo(resourceManager);
    }

    // Create an operation manager
    smtk::operation::Manager::Ptr operationManager = smtk::operation::Manager::create();

    // Register rgg operators to the operation manager
    {
      smtk::session::rgg::Registrar::registerTo(operationManager);
    }

    // Register the resource manager to the operation manager (newly created
    // resources will be automatically registered to the resource manager).
    operationManager->registerResourceManager(resourceManager);

    if (exportAndValidateInpFiles(model))
    {
      std::cerr << "Fail to export and valid the target core" <<std::endl;
      return 1;
    }
  }
  return 0;
}
