//=========================================================================
//  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/ace3p/operations/RemoveStage.h"

#include "smtk/simulation/ace3p/RemoveStage_xml.h"

// Project includes
#include "smtk/simulation/ace3p/Project.h"

// SMTK includes
#include "smtk/attribute/Attribute.h"
#include "smtk/attribute/IntItem.h"
#include "smtk/attribute/Resource.h"
#include "smtk/io/Logger.h"
#include "smtk/model/Resource.h"
#include "smtk/resource/Manager.h"

namespace smtk
{
namespace simulation
{
namespace ace3p
{

smtk::operation::Operation::Result RemoveStage::operateInternal()
{
  auto refItem = this->parameters()->associations();
  auto project = refItem->valueAs<smtk::simulation::ace3p::Project>();

  int index = this->parameters()->findInt("stage-index")->value();
  int currentStageIndex = static_cast<int>(project->currentStageIndex());

  // Get the stage's resources first
  auto attResource = project->stage(index)->attributeResource();
  auto modelResource = project->stage(index)->modelResource();

  // Remove stage from the project
  bool success = project->removeStage(index);

  smtk::resource::ManagerPtr resManager =
    std::dynamic_pointer_cast<smtk::resource::Resource>(project)->manager();

  attResource->setMarkedForRemoval(true);

  // Remove attribute resource from project and resource manager
  if (!resManager->remove(attResource))
  {
    smtkErrorMacro(this->log(), "Failed to remove attribute resource from resource manager.");
    success = false;
  }
  if (!project->resources().remove(attResource))
  {
    smtkErrorMacro(this->log(), "Failed to remove attribute resource from resource manager.");
    success = false;
  }

  std::size_t n = project->numberOfStages();
  int count = 0;
  for (std::size_t i = 0; i < n; ++i)
  {
    count += project->stage(i)->modelResource() == modelResource;
  }

  if (count == 0)
  {
    modelResource->setMarkedForRemoval(true);

    // Remove model resource from project and resource manager
    if (!resManager->remove(modelResource))
    {
      smtkErrorMacro(this->log(), "Failed to remove model resource from resource manager.");
      success = false;
    }
    if (!project->resources().remove(modelResource))
    {
      smtkErrorMacro(this->log(), "Failed to remove model resource from resource manager.");
      success = false;
    }
  }

  auto result = this->createResult(smtk::operation::Operation::Outcome::SUCCEEDED);
  if (success)
  {
    if (index < currentStageIndex)
    {
      currentStageIndex -= 1;
    }
    else if (index == currentStageIndex)
    {
      currentStageIndex = -1;
    }
    project->setCurrentStage(currentStageIndex, true); // marks the project as dirty
  }
  else
  {
    result = this->createResult(smtk::operation::Operation::Outcome::FAILED);
  }
  return result;
}

smtk::operation::Operation::Specification RemoveStage::createSpecification()
{
  Specification spec = this->smtk::operation::XMLOperation::createSpecification();
  return spec;
}

const char* RemoveStage::xmlDescription() const
{
  return RemoveStage_xml;
}

} // namespace ace3p
} // namespace simulation
} // namespace smtk
