//=========================================================================
//  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/session/aeva/Operation.h"
#include "smtk/session/aeva/Resource.h"
#include "smtk/session/aeva/Session.h"

#include "smtk/attribute/Attribute.h"
#include "smtk/attribute/ReferenceItem.h"
#include "smtk/attribute/Resource.h"
#include "smtk/attribute/ResourceItem.h"

#include "vtkDataObject.h"

namespace smtk
{
namespace session
{
namespace aeva
{

bool Operation::fetchResourceAndSession(std::shared_ptr<Resource>& resource,
  std::shared_ptr<Session>& session) const
{
  auto assoc = this->parameters()->associations();
  if (assoc && assoc->isEnabled() && assoc->isSet(0))
  {
    resource = dynamic_pointer_cast<Resource>(assoc->value(0));
    if (!resource)
    {
      auto comp = dynamic_pointer_cast<smtk::resource::Component>(assoc->value(0));
      if (comp)
      {
        resource = dynamic_pointer_cast<Resource>(comp->resource());
      }
    }
    if (resource)
    {
      session = resource->session();
    }
  }
  return resource && session;
}

void Operation::prepareResourceAndSession(Result& result,
  std::shared_ptr<Resource>& resource,
  std::shared_ptr<Session>& session,
  bool allowCreate)
{
  this->fetchResourceAndSession(resource, session);

  // Create a new resource for the import if needed.
  if (!resource && allowCreate)
  {
    auto manager = this->specification()->manager();
    if (manager)
    {
      resource = manager->create<smtk::session::aeva::Resource>();
    }
    else
    {
      resource = smtk::session::aeva::Resource::create();
    }
    auto resultResources = result->findResource("resource");
    if (resultResources)
    {
      resultResources->setValue(resource);
    }
  }
  if (!session)
  {
    session = smtk::session::aeva::Session::create();
    resource->setSession(session);
  }
}

bool Operation::allValuesHaveStorage(const smtk::attribute::ReferenceItem& item)
{
  for (std::size_t ii = 0; ii < item.numberOfValues(); ++ii)
  {
    if (!item.isSet(ii))
    {
      continue;
    }
    auto target = item.valueAs<smtk::resource::Component>(ii);
    auto resource = std::dynamic_pointer_cast<smtk::session::aeva::Resource>(target->resource());
    auto session = resource ? resource->session() : smtk::session::aeva::Session::Ptr();
    if (!session)
    {
      return false;
    }
    vtkSmartPointer<vtkDataObject> targetData;
    if (!target || !(targetData = session->findStorage(target->id())))
    {
      return false;
    }
  }
  return true;
}

vtkSmartPointer<vtkDataObject> Operation::getData(const smtk::resource::PersistentObjectPtr ptr)
{
  // Get the model, resource, and session of the persistent object ptr
  smtk::model::Model model = ptr->as<smtk::model::Entity>()->owningModel();
  smtk::session::aeva::Resource::Ptr resource =
    model.resource()->as<smtk::session::aeva::Resource>();
  smtk::session::aeva::Session::Ptr session = resource->session();

  return session->findStorage(ptr->id());
}

} // namespace aeva
} //namespace session
} // namespace smtk
