//=========================================================================
//  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_SelectionResponder_h
#define smtk_session_aeva_SelectionResponder_h
#if !defined(__VTK_WRAP__) && defined(SMTK_ENABLE_PARAVIEW_SUPPORT)

#include "smtk/extension/paraview/server/RespondToVTKSelection.h"
#include "smtk/session/aeva/Exports.h" // For export macro

#include "vtkSmartPointer.h"

class vtkDataObject;

namespace smtk
{
namespace session
{
namespace aeva
{

class Resource;
class Session;

/**\brief An operation that handles cell selections on mesh resources.
  *
  * This operation, invoked with a vtkSelection dataset, creates a
  * new meshset and adds it to the SMTK selection when VTK cell indices
  * are provided.
  */
class SMTKAEVASESSION_EXPORT SelectionResponder : public smtk::view::RespondToVTKSelection
{
public:
  using Result = smtk::operation::Operation::Result;
  smtkTypeMacro(SelectionResponder);
  smtkCreateMacro(SelectionResponder);
  smtkSharedFromThisMacro(smtk::view::RespondToVTKSelection);
  smtkSuperclassMacro(smtk::view::RespondToVTKSelection);
  ~SelectionResponder() override;

protected:
  SelectionResponder();

  /// A utility for methods that need the resource being processed.
  bool fetchResourceAndSession(std::shared_ptr<Resource>& resource,
    std::shared_ptr<Session>& session) const;

  /// Examine the SMTK selection and, if it contains a single side-set, return that.
  std::shared_ptr<smtk::model::Entity> selectedSideSet() const;

  /// Append primitives from SMTK selection into one data object.
  vtkSmartPointer<vtkDataObject> appendCellPrimitives(bool includeExistingPrimitiveSelection);

  /// Append primitives from VTK selection into one data object.
  vtkSmartPointer<vtkDataObject> appendSelectedPrimitives(bool includeExistingPrimitiveSelection);

  /**\brief Replace selection with primitive selection.
    *
    * This will create a new polydata object bound to a new cells
    * and select it.
    *
    * Note that the selection is filtered.
    */
  bool replaceWithPrimitiveSelection(Result& result);

  /**\brief Add to existing selection.
    *
    * If the SMTK selection contains a single side set,
    * then update the side set to include the primitives
    * in VTK selection (assuming they are from the same model).
    *
    * Otherwise, create a new polydata object bound to the
    * selected VTK primitives and a matching PrimitiveSelection
    * cell in SMTK.
    *
    * Note that the selection is filtered.
    */
  bool addPrimitiveSelection(Result& result);

  /**\brief Subtract from existing selection.
    *
    * If the SMTK selection contains a single side set,
    * then update the side set to remove the primitives
    * in VTK selection (assuming any are in the side set).
    *
    * Otherwise, if a PrimitiveSelection object is in the
    * SMTK selection, remove the selected VTK primitives
    * from it and mark its geometry as modified.
    *
    * Note that the selection is filtered.
    */
  bool subtractPrimitiveSelection(Result& result);

  /**\brief XOR with the existing selection..
    *
    * If the SMTK selection contains a single side set,
    * then update the side set to remove the primitives
    * in VTK selection (assuming any are in the side set).
    *
    * Otherwise, if a PrimitiveSelection object is in the
    * SMTK selection, remove the selected VTK primitives
    * from it and mark its geometry as modified.
    *
    * Note that the selection is filtered.
    */
  bool xorPrimitiveSelection(Result& result);

  /// Simply call transcribeCellIdSelection().
  Result operateInternal() override;

private:
  const char* xmlDescription() const override;
};

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

#endif // !defined(__VTK_WRAP__) && defined(SMTK_ENABLE_PARAVIEW_SUPPORT)
#endif // smtk_session_aeva_SelectionResponder_h
