//=========================================================================
//  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.
//=========================================================================
#ifndef smtk_session_aeva_CellSelection_h
#define smtk_session_aeva_CellSelection_h

#include "smtk/session/aeva/Exports.h"

#include "smtk/model/Entity.h"

#include "vtkSmartPointer.h"

class vtkDataObject;

namespace smtk
{
namespace session
{
namespace aeva
{

class Resource;

/**\brief Temporarily hold a selection of cells from discrete model entities.
  *
  * The static create() method returns an aliased shared-pointer that,
  * when it goes out of scope, will delete the entity's data from the
  * aeva session via an operation (whose output is used to update any
  * GUI components that may be presenting the selection).
  */
class SMTKAEVASESSION_EXPORT CellSelection : public smtk::model::Entity
{
public:
  smtkTypeMacro(smtk::session::aeva::CellSelection);
  smtkSharedFromThisMacro(smtk::resource::PersistentObject);

  CellSelection(const std::shared_ptr<Resource>& parent, vtkDataObject* selectedCells);
  ~CellSelection() override = default;

  std::string name() const override { return "primitive selection"; }

  /// Return the selective primitives
  vtkSmartPointer<vtkDataObject> data() const;

  /// Update the set of selected cells.
  ///
  /// This replaces the session's VTK data storage with the given \a selectedCells
  /// and marks the CellSelection component as having modified geometry.
  void replaceData(vtkDataObject* selectedCells);

  /// Create an aliased CellSelection.
  ///
  /// The \a selectedCells data object is expected to have global point/cell
  /// IDs present on primary geometry in the given \a parent resource.
  static std::shared_ptr<CellSelection> create(const std::shared_ptr<Resource>& parent,
    vtkDataObject* selectedCells,
    const std::weak_ptr<smtk::operation::Manager>& operationManager);

  /// Create an aliased CellSelection.
  ///
  /// This variant accepts a list of global cell IDs and is used for testing.
  static std::shared_ptr<CellSelection> create(const std::shared_ptr<Resource>& parent,
    const std::set<vtkIdType>& cellIdsIn,
    const std::weak_ptr<smtk::operation::Manager>& operationManager);

  /// Do not create a CellSelection, but if one exists, return its pointer.
  static std::shared_ptr<CellSelection> instance() { return s_instance.lock(); }

private:
  // Hold a weak pointer to the most recently created object.
  static std::weak_ptr<CellSelection> s_instance;

  // Modify the access level of links to prevent their explicit use.
  Links& links() override { return smtk::resource::Component::links(); }
  const Links& links() const override { return smtk::resource::Component::links(); }
};

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

#endif // smtk_session_aeva_CellSelection_h
