// Copyright (c) 1997-1999 Matra Datavision
// Copyright (c) 1999-2015 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.

#ifndef _ViewerTest_HeaderFile
#define _ViewerTest_HeaderFile

#include <Aspect_TypeOfLine.hxx>
#include <Aspect_TypeOfMarker.hxx>
#include <Aspect_TypeOfTriedronPosition.hxx>
#include <Draw_Interpretor.hxx>
#include <Graphic3d_TypeOfShadingModel.hxx>
#include <NCollection_Vec2.hxx>
#include <Standard_TypeDef.hxx>
#include <Graphic3d_ZLayerId.hxx>
#include <Standard_Transient.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_HArray1.hxx>
#include <TopoDS_Shape.hxx>
#include <NCollection_List.hxx>
#include <Quantity_ColorRGBA.hxx>

class AIS_InteractiveContext;
class AIS_InteractiveObject;
class Image_PixMap;
class V3d_View;
class V3d_Viewer;
class ViewerTest_EventManager;
class TopoDS_Shape;
class WNT_WClass;

//! Parameters for creating new view.
struct ViewerTest_VinitParams
{
  TCollection_AsciiString       ViewName;
  TCollection_AsciiString       DisplayName;
  occ::handle<V3d_View>         ViewToClone;
  occ::handle<V3d_View>         ParentView;
  NCollection_Vec2<double>      Offset;
  NCollection_Vec2<double>      Size;
  Aspect_TypeOfTriedronPosition Corner;
  NCollection_Vec2<int>         SubviewMargins;
  bool                          IsVirtual;
  bool                          IsComposer;

  ViewerTest_VinitParams()
      : Corner(Aspect_TOTP_LEFT_UPPER),
        IsVirtual(false),
        IsComposer(false)
  {
  }
};

class ViewerTest
{
public:
  DEFINE_STANDARD_ALLOC

  //! Loads all Draw commands of V2d & V3d. Used for plugin.
  Standard_EXPORT static void Factory(Draw_Interpretor& theDI);

  //! Creates view with default or custom name and adds this name in map to manage multiple views.
  //! Implemented in ViewerTest_ViewerCommands.cxx.
  Standard_EXPORT static TCollection_AsciiString ViewerInit(
    const ViewerTest_VinitParams& theParams);

  //! Creates view.
  static TCollection_AsciiString ViewerInit(const TCollection_AsciiString& theViewName = "")
  {
    ViewerTest_VinitParams aParams;
    aParams.ViewName = theViewName;
    return ViewerInit(aParams);
  }

  //! Creates view.
  static TCollection_AsciiString ViewerInit(
    const int                      thePxLeft,
    const int                      thePxTop,
    const int                      thePxWidth,
    const int                      thePxHeight,
    const TCollection_AsciiString& theViewName,
    const TCollection_AsciiString& theDisplayName = "",
    const occ::handle<V3d_View>&   theViewToClone = occ::handle<V3d_View>(),
    const bool                     theIsVirtual   = false)
  {
    ViewerTest_VinitParams aParams;
    aParams.Offset.SetValues((float)thePxLeft, (float)thePxTop);
    aParams.Size.SetValues((float)thePxWidth, (float)thePxHeight);
    aParams.ViewName    = theViewName;
    aParams.DisplayName = theDisplayName;
    aParams.ViewToClone = theViewToClone;
    aParams.IsVirtual   = theIsVirtual;
    return ViewerInit(aParams);
  }

  Standard_EXPORT static void RemoveViewName(const TCollection_AsciiString& theName);

  Standard_EXPORT static void InitViewName(const TCollection_AsciiString& theName,
                                           const occ::handle<V3d_View>&   theView);

  Standard_EXPORT static TCollection_AsciiString GetCurrentViewName();

  //! Make the view active
  Standard_EXPORT static void ActivateView(const occ::handle<V3d_View>& theView, bool theToUpdate);

  //! Removes view and clear all maps
  //! with information about its resources if necessary
  Standard_EXPORT static void RemoveView(const TCollection_AsciiString& theViewName,
                                         const bool                     theToRemoveContext = true);

  //! Removes view and clear all maps
  //! with information about its resources if necessary
  Standard_EXPORT static void RemoveView(const occ::handle<V3d_View>& theView,
                                         const bool                   theToRemoveContext = true);

  //! Display AIS object in active Viewer and register it in the map of Interactive Objects with
  //! specified name.
  //! @param theName            key to be associated to displayed interactive object
  //! @param theObject          object to display
  //! @param theToUpdate        redraw viewer after displaying object
  //! @param theReplaceIfExists replace the object assigned to specified key
  //! @return true if new object has been displayed
  Standard_EXPORT static bool Display(const TCollection_AsciiString&            theName,
                                      const occ::handle<AIS_InteractiveObject>& theObject,
                                      const bool                                theToUpdate = true,
                                      const bool theReplaceIfExists                         = true);

  //! waits until a shape of type <aType> is picked in the AIS Viewer and returns it.
  //! if <aType> == TopAbs_Shape, any shape can be picked...
  //! MaxPick is the Max number before exiting, if no pick is successful
  Standard_EXPORT static TopoDS_Shape PickShape(const TopAbs_ShapeEnum aType,
                                                const int              MaxPick = 5);

  //! wait until the array is filled with picked shapes.
  //! returns True if the array is filled.
  //! exit if number of unsuccessful picks = <MaxPick>
  Standard_EXPORT static bool PickShapes(const TopAbs_ShapeEnum                          aType,
                                         occ::handle<NCollection_HArray1<TopoDS_Shape>>& thepicked,
                                         const int MaxPick = 5);

  Standard_EXPORT static void Commands(Draw_Interpretor& theCommands);

  Standard_EXPORT static void ViewerCommands(Draw_Interpretor& theCommands);

  Standard_EXPORT static void RelationCommands(Draw_Interpretor& theCommands);

  Standard_EXPORT static void ObjectCommands(Draw_Interpretor& theCommands);

  Standard_EXPORT static void FilletCommands(Draw_Interpretor& theCommands);

  Standard_EXPORT static void OpenGlCommands(Draw_Interpretor& theCommands);

  Standard_EXPORT static void GetMousePosition(int& xpix, int& ypix);

  Standard_EXPORT static occ::handle<V3d_Viewer> GetViewerFromContext();

  Standard_EXPORT static occ::handle<V3d_Viewer> GetCollectorFromContext();

  Standard_EXPORT static const occ::handle<AIS_InteractiveContext>& GetAISContext();

  Standard_EXPORT static void SetAISContext(const occ::handle<AIS_InteractiveContext>& aContext);

  Standard_EXPORT static const occ::handle<V3d_View>& CurrentView();

  Standard_EXPORT static void CurrentView(const occ::handle<V3d_View>& aViou);

  Standard_EXPORT static void Clear();

  //! puts theMgr as current eventmanager (the move,select,...will be applied to theMgr)
  Standard_EXPORT static void SetEventManager(const occ::handle<ViewerTest_EventManager>& theMgr);

  //! removes the last EventManager from the list.
  Standard_EXPORT static void UnsetEventManager();

  //! clear the list of EventManagers and
  //! sets the default EventManager as current
  Standard_EXPORT static void ResetEventManager();

  Standard_EXPORT static occ::handle<ViewerTest_EventManager> CurrentEventManager();

  Standard_EXPORT static void RemoveSelected();

  //! redraws all defined views.
  Standard_EXPORT static void RedrawAllViews();

  //! Splits "parameter=value" string into separate
  //! parameter and value strings.
  //! @return TRUE if the string matches pattern "<string>=<empty or string>"
  Standard_EXPORT static bool SplitParameter(const TCollection_AsciiString& theString,
                                             TCollection_AsciiString&       theName,
                                             TCollection_AsciiString&       theValue);

  //! Returns list of selected shapes.
  Standard_EXPORT static void GetSelectedShapes(NCollection_List<TopoDS_Shape>& theShapes);

  //! Parses line type argument.
  //! Handles either enumeration (integer) value or string constant.
  Standard_EXPORT static bool ParseLineType(const char*        theArg,
                                            Aspect_TypeOfLine& theType,
                                            uint16_t&          thePattern);

  //! Parses line type argument.
  //! Handles either enumeration (integer) value or string constant.
  static bool ParseLineType(const char* theArg, Aspect_TypeOfLine& theType)
  {
    uint16_t aPattern = 0xFFFF;
    return ParseLineType(theArg, theType, aPattern);
  }

  //! Parses marker type argument.
  //! Handles either enumeration (integer) value or string constant.
  Standard_EXPORT static bool ParseMarkerType(const char*                theArg,
                                              Aspect_TypeOfMarker&       theType,
                                              occ::handle<Image_PixMap>& theImage);

  //! Parses shading model argument.
  //! Handles either enumeration (integer) value or string constant.
  Standard_EXPORT static bool ParseShadingModel(const char*                   theArg,
                                                Graphic3d_TypeOfShadingModel& theModel);

  //! Parses ZLayer name.
  //! @param[in] theArg  layer name or enumeration alias
  //! @param[out] theLayer  layer index
  //! @return TRUE if layer has been identified, note that Graphic3d_ZLayerId_UNKNOWN is also valid
  //! value
  static bool ParseZLayerName(const char* theArg, Graphic3d_ZLayerId& theLayer)
  {
    return parseZLayer(theArg, false, theLayer);
  }

  //! Parses ZLayer name.
  //! @param[in] theArg  layer name, enumeration alias or index (of existing Layer)
  //! @param[out] theLayer  layer index
  //! @return TRUE if layer has been identified, note that Graphic3d_ZLayerId_UNKNOWN is also valid
  //! value
  static bool ParseZLayer(const char* theArg, Graphic3d_ZLayerId& theLayer)
  {
    return parseZLayer(theArg, true, theLayer);
  }

  //! Auxiliary method to parse transformation persistence flags
  Standard_EXPORT static bool ParseCorner(const char*                    theArg,
                                          Aspect_TypeOfTriedronPosition& theCorner);

public: //! @name deprecated methods
  //! Parses RGB(A) color argument(s) specified within theArgVec[0], theArgVec[1], theArgVec[2] and
  //! theArgVec[3].
  Standard_DEPRECATED("Method has been moved to Draw::ParseColor()")
  Standard_EXPORT static int ParseColor(const int                theArgNb,
                                        const char* const* const theArgVec,
                                        Quantity_ColorRGBA&      theColor);

  //! Parses RGB color argument(s).
  //! Returns number of handled arguments (1 or 3) or 0 on syntax error.
  Standard_DEPRECATED("Method has been moved to Draw::ParseColor()")
  Standard_EXPORT static int ParseColor(const int                theArgNb,
                                        const char* const* const theArgVec,
                                        Quantity_Color&          theColor);

  //! Parses boolean argument.
  //! Handles either flag specified by 0|1 or on|off.
  Standard_DEPRECATED("Method has been moved to Draw::ParseOnOff()")
  Standard_EXPORT static bool ParseOnOff(const char* theArg, bool& theIsOn);

  Standard_DEPRECATED("Method has been moved to Quantity_Color::ColorFromName()")
  Standard_EXPORT static Quantity_NameOfColor GetColorFromName(const char* name);

private:
  //! Parses ZLayer name.
  //! @param[in] theArg  layer name, enumeration alias or index (of existing Layer)
  //! @param[in] theToAllowInteger  when TRUE, the argument will be checked for existing layer index
  //! @param[out] theLayer  layer index
  //! @return TRUE if layer has been identified, note that Graphic3d_ZLayerId_UNKNOWN is also valid
  //! value
  Standard_EXPORT static bool parseZLayer(const char*         theArg,
                                          bool                theToAllowInteger,
                                          Graphic3d_ZLayerId& theLayer);

  //! Returns a window class that implements standard behavior of
  //! all windows of the ViewerTest. This includes usual Open CASCADE
  //! view conventions for mouse buttons (e.g. Ctrl+MB1 for zoom,
  //! Ctrl+MB2 for pan, etc) and keyboard shortcuts.
  //! This method is relevant for MS Windows only and respectively
  //! returns WNT_WClass handle.
  static const occ::handle<WNT_WClass>& WClass();
};

#endif // _ViewerTest_HeaderFile
