#ifndef __vtkMRMLLayoutNode_h
#define __vtkMRMLLayoutNode_h

// MRML includes
#include "vtkMRMLAbstractLayoutNode.h"

class vtkXMLDataElement;
class vtkMRMLAbstractViewNode;

/// \brief Node that describes the view layout of the application.
///
/// When the scene is closing (vtkMRMLScene::Clear), the view arrangement is
/// set to none due to the Copy() call on an empty node.
class VTK_MRML_EXPORT vtkMRMLLayoutNode : public vtkMRMLAbstractLayoutNode
{
public:
  static vtkMRMLLayoutNode* New();
  vtkTypeMacro(vtkMRMLLayoutNode, vtkMRMLAbstractLayoutNode);
  vtkMRMLNode* CreateNodeInstance() override;
  void PrintSelf(ostream& os, vtkIndent indent) override;

  //--------------------------------------------------------------------------
  /// MRML methods
  //--------------------------------------------------------------------------

  /// Set node attributes
  void ReadXMLAttributes(const char** atts) override;

  /// Write this node's information to a MRML file in XML format.
  void WriteXML(ostream& of, int indent) override;

  /// Copy the node's attributes to this object
  void CopyContent(vtkMRMLNode* node, bool deepCopy = true) override;

  /// \brief Reimplemented to reset maximized view node.
  void Reset(vtkMRMLNode* defaultNode) override;

  /// Get/Set for Current layout
  vtkGetMacro(ViewArrangement, int);
  virtual void SetViewArrangement(int);

  vtkGetMacro(GUIPanelVisibility, int);
  vtkSetMacro(GUIPanelVisibility, int);

  vtkGetMacro(BottomPanelVisibility, int);
  vtkSetMacro(BottomPanelVisibility, int);

  /// 0 is left side, 1 is right side
  vtkGetMacro(GUIPanelLR, int);
  vtkSetMacro(GUIPanelLR, int);

  /// Control the collapse state of the SliceControllers
  vtkGetMacro(CollapseSliceControllers, int);
  vtkSetMacro(CollapseSliceControllers, int);

  /// CompareView configuration Get/Set methods
  vtkGetMacro(NumberOfCompareViewRows, int);
  vtkSetClampMacro(NumberOfCompareViewRows, int, 1, 50);
  vtkGetMacro(NumberOfCompareViewColumns, int);
  vtkSetClampMacro(NumberOfCompareViewColumns, int, 1, 50);

  /// @{
  /// \deprecated
  /// Following removal of the LightBox feature, compareView lightbox configuration
  /// through Get/Set methods is not supported.
  int GetNumberOfCompareViewLightboxRows()
  {
    vtkWarningMacro("" << __func__ << ": Function is deprecated. LightBox support has been removed.");
    return 1;
  }
  void SetNumberOfCompareViewLightboxRows(int vtkNotUsed(value)) //
  {
    vtkWarningMacro("" << __func__ << ": Function is deprecated. LightBox support has been removed.");
  }
  int GetNumberOfCompareViewLightboxRowsMinValue()
  {
    vtkWarningMacro("" << __func__ << ": Function is deprecated. LightBox support has been removed.");
    return 1;
  }
  int GetNumberOfCompareViewLightboxRowsMaxValue()
  {
    vtkWarningMacro("" << __func__ << ": Function is deprecated. LightBox support has been removed.");
    return 1;
  }
  int GetNumberOfCompareViewLightboxColumns()
  {
    vtkWarningMacro("" << __func__ << ": Function is deprecated. LightBox support has been removed.");
    return 1;
  }
  void SetNumberOfCompareViewLightboxColumns(int vtkNotUsed(value)) //
  {
    vtkWarningMacro("" << __func__ << ": Function is deprecated. LightBox support has been removed.");
  }
  int GetNumberOfCompareViewLightboxColumnsMinValue()
  {
    vtkWarningMacro("" << __func__ << ": Function is deprecated. LightBox support has been removed.");
    return 1;
  }
  int GetNumberOfCompareViewLightboxColumnsMaxValue()
  {
    vtkWarningMacro("" << __func__ << ": Function is deprecated. LightBox support has been removed.");
    return 1;
  }
  /// @}

  /// Set/Get the size of the main and secondary panels (size of Frame1
  /// in each panel)
  vtkGetMacro(MainPanelSize, int);
  vtkSetMacro(MainPanelSize, int);
  vtkGetMacro(SecondaryPanelSize, int);
  vtkSetMacro(SecondaryPanelSize, int);

  /// Set/Get the name of the last selected module
  /// Note: this is property is no longer used and may be removed in the future.
  vtkGetStringMacro(SelectedModule);
  vtkSetStringMacro(SelectedModule);

  /// Set/Get the N-th view that are temporarily shown maximized.
  /// Only one view can be maximized in each viewport.
  vtkMRMLAbstractViewNode* GetMaximizedViewNode(int maximizedViewNodeIndex);
  int GetNumberOfMaximizedViewNodes();
  void AddMaximizedViewNode(vtkMRMLAbstractViewNode* maximizedViewNode);
  void RemoveMaximizedViewNode(vtkMRMLAbstractViewNode* maximizedViewNode);
  void RemoveAllMaximizedViewNodes();
  bool IsMaximizedViewNode(vtkMRMLAbstractViewNode* viewNode);

  /// Get node XML tag name (like Volume, Model)
  const char* GetNodeTagName() override { return "Layout"; }

  enum SlicerLayout
  {
    SlicerLayoutInitialView = 0,
    SlicerLayoutDefaultView = 1,
    SlicerLayoutConventionalView = 2,
    SlicerLayoutFourUpView = 3,
    SlicerLayoutOneUp3DView = 4,
    SlicerLayoutOneUpRedSliceView = 6,
    SlicerLayoutOneUpYellowSliceView = 7,
    SlicerLayoutOneUpGreenSliceView = 8,
    SlicerLayoutTabbed3DView = 9,
    SlicerLayoutTabbedSliceView = 10,
    SlicerLayoutCompareView = 12,
    SlicerLayoutNone = 14,
    SlicerLayoutDual3DView = 15,
    SlicerLayoutConventionalWidescreenView = 16,
    SlicerLayoutTriple3DEndoscopyView = 19, // Up to here, all layouts are Slicer 3 compatible
    SlicerLayoutThreeOverThreeView = 21,
    SlicerLayoutFourOverFourView = 22,
    SlicerLayoutCompareGridView = 23,
    SlicerLayoutTwoOverTwoView = 27,
    SlicerLayoutSideBySideView = 29,
    SlicerLayoutFourByThreeSliceView = 30,
    SlicerLayoutFourByTwoSliceView = 31,
    SlicerLayoutFiveByTwoSliceView = 32,
    SlicerLayoutThreeByThreeSliceView = 33,
    SlicerLayoutFourUpTableView = 34,
    SlicerLayout3DTableView = 35,
    SlicerLayoutConventionalPlotView = 36,
    SlicerLayoutFourUpPlotView = 37,
    SlicerLayoutFourUpPlotTableView = 38,
    SlicerLayoutOneUpPlotView = 39,
    SlicerLayoutThreeOverThreePlotView = 40,
    SlicerLayoutDicomBrowserView = 41,
    SlicerLayoutDualMonitorFourUpView = 42,
    SlicerLayoutFinalView, // special value, must be placed after the last standard view (used for iterating through all the views)

    SlicerLayoutMaximizedView = 98,
    SlicerLayoutCustomView = 99,
    SlicerLayoutUserView = 100
  };

  /// Adds a layout description with integer identifier
  /// "layout". Returns false without making any modifications if the
  /// integer identifier "layout" has already been added.
  bool AddLayoutDescription(int layout, const char* layoutDescription);

  /// Modifies a layout description for integer identifier
  /// "layout". Returns false without making any modifications if the
  /// integer identifier "layout" has NOT already been added.
  /// If layoutDescription is empty then the layout is removed.
  bool SetLayoutDescription(int layout, const char* layoutDescription);

  /// Get list of all specified layout indices
  std::vector<int> GetLayoutIndices();

  /// Query whether a layout exists with a specified integer identifier
  bool IsLayoutDescription(int layout);

  /// Get the layout description associated with a specified integer
  /// identifier. The empty string is returned if the layout does not exist.
  std::string GetLayoutDescription(int layout);

  /// Copy all layout descriptions from the specified layout node.
  /// All the previous layout descriptions are replaced.
  void CopyLayoutDescriptions(vtkMRMLLayoutNode* source);

  // Get the layout description currently displayed. Used
  // internally. This is XML description corresponding to the ivar
  // ViewArrangement which is the integer identifier for the
  // layout. ViewArrangement and CurrentViewDescription may not
  // correspond while a view is being switched.
  vtkGetStringMacro(CurrentLayoutDescription);

  // Get the XML data model of the CurrentViewDescription
  vtkGetObjectMacro(LayoutRootElement, vtkXMLDataElement);

  // You are responsible to delete the returned dataElement.
  static vtkXMLDataElement* ParseLayout(const char* description);

protected:
  void UpdateCurrentLayoutDescription();
  void SetAndParseCurrentLayoutDescription(const char* description);
  vtkSetStringMacro(CurrentLayoutDescription);

protected:
  vtkMRMLLayoutNode();
  ~vtkMRMLLayoutNode() override;
  vtkMRMLLayoutNode(const vtkMRMLLayoutNode&);
  void operator=(const vtkMRMLLayoutNode&);

  int GUIPanelVisibility;
  int BottomPanelVisibility;
  int GUIPanelLR;
  int CollapseSliceControllers;
  int ViewArrangement;
  int NumberOfCompareViewRows;
  int NumberOfCompareViewColumns;

  char* SelectedModule;

  int MainPanelSize;
  int SecondaryPanelSize;

  std::map<int, std::string> Layouts;
  char* CurrentLayoutDescription;
  vtkXMLDataElement* LayoutRootElement;
};

#endif
