// Created on: 2020-01-25
// Created by: Natalia ERMOLAEVA
// Copyright (c) 2020 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 TreeModel_ItemProperties_H
#define TreeModel_ItemProperties_H

#include <Standard.hxx>
#include <Standard_Dump.hxx>
#include <Standard_Handle.hxx>
#include <Standard_Macro.hxx>
#include <Standard_Type.hxx>
#include <Standard_Transient.hxx>

#include <NCollection_IndexedDataMap.hxx>
#include <NCollection_IndexedMap.hxx>
#include <NCollection_List.hxx>

#include <TCollection_AsciiString.hxx>

#include <inspector/TreeModel_ItemBase.hxx>
#include <inspector/ViewControl_EditType.hxx>

#include <Standard_WarningsDisable.hxx>
#include <QAbstractTableModel>
#include <QColor>
#include <QList>
#include <QModelIndexList>
#include <QVariant>
#include <Standard_WarningsRestore.hxx>

//! \class TreeModel_ItemProperties
//! Class to manipulate properties of tree item. The properties are organized in table structure
class TreeModel_ItemProperties : public Standard_Transient
{
  //! enum defined the dimension type
  enum TreeModel_DimType
  {
    TreeModel_DimType_Rows,   //!< defines number of rows
    TreeModel_DimType_Columns //!< defines number of columns
  };

  //! container of values in a row of property table
  struct TreeModel_RowValue
  {
    TreeModel_RowValue(const Standard_Integer theValueStartPosition,
                       const QVariant&        theKey,
                       QVariant               theValue)
        : ValueStartPosition(theValueStartPosition),
          Key(theKey),
          Value(theValue)
    {
    }

    Standard_Integer ValueStartPosition; //!< start position of the key
    QVariant         Key;                //!< value in the first column
    QVariant         Value;              //!< value in the second column
    QMap<int, QVariant>
      CustomValues; //!< custom values, e.g. key is Background, value is a defined color
  };

public:
  //! Constructor
  TreeModel_ItemProperties() {}

  //! Destructor
  ~TreeModel_ItemProperties() {}

  //! Sets the current item
  void SetItem(const TreeModel_ItemBasePtr& theItem) { myItem = theItem; }

  //! Fills properties with the stream value
  Standard_EXPORT void InitByStream(const Standard_SStream& theStream);

  //! Returns the current item
  TreeModel_ItemBasePtr Item() const { return myItem; }

  //! Fills internal containers by item stream values
  Standard_EXPORT void Init();

  //! If the item has internal values, they should be reset here.
  Standard_EXPORT void Reset();

  //! Returns number of table rows
  //! \return an integer value
  Standard_EXPORT int RowCount() const;

  //! Returns number of table columns
  //! \return an integer value
  int ColumnCount() const { return 2; }

  //! Returns content of the model index for the given role, it is obtained from internal container
  //! of values \param theRow a model index row \param theColumn a model index column \param theRole
  //! a view role \return value interpreted depending on the given role
  Standard_EXPORT QVariant Data(const int theRow,
                                const int theColumn,
                                int       theRole = Qt::DisplayRole) const;

  //! Returns type of edit control for the model index. By default, it is an empty control
  //! \param theRow a model index row
  //! \param theColumn a model index column
  //! \return edit type
  Standard_EXPORT ViewControl_EditType EditType(const int theRow, const int theColumn) const;

  //! Sets content of the model index for the given role, it is applied to internal container of
  //! values \param theRow a model index row \param theColumn a model index column \param theRole a
  //! view role \return true if the value is changed
  Standard_EXPORT bool SetData(const int       theRow,
                               const int       theColumn,
                               const QVariant& theValue,
                               int             theRole = Qt::DisplayRole);

  //! Returns presentation of the attribute to be visualized in the view
  //! \thePresentations[out]  container of presentation handles to be visualized
  Standard_EXPORT void Presentations(
    NCollection_List<Handle(Standard_Transient)>& thePresentations);

  //! Returns flags for the item: ItemIsEnabled | Qt::ItemIsSelectable.
  //! Additional flag for the column 1 is Qt::ItemIsEditable.
  //! \param theIndex a model index
  //! \return flags
  Standard_EXPORT Qt::ItemFlags TableFlags(const int theRow, const int theColumn) const;

  //! Returns stream value of the item to fulfill property panel.
  //! \return stream value or dummy
  Standard_EXPORT void ChildStream(const int                theRowId,
                                   TCollection_AsciiString& theKey,
                                   Standard_DumpValue&      theValue) const;

  //! Returns data object of the item.
  //! \return object key
  const TCollection_AsciiString& Key() const { return myKey; }

  //! Returns stream value of the item.
  //! \return value
  const TCollection_AsciiString& StreamValue() const { return myStreamValue.myValue; }

  //! Returns children stream values
  // const NCollection_IndexedDataMap<TCollection_AsciiString, Standard_DumpValue>& Values() const {
  // initItem(); return myValues; }

  //! Returns children stream values
  const NCollection_IndexedDataMap<Standard_Integer, TreeModel_RowValue>& RowValues() const
  {
    initItem();
    return myRowValues;
  }

  //! Returns children stream values
  const NCollection_IndexedDataMap<TCollection_AsciiString, Standard_DumpValue>& Children() const
  {
    initItem();
    return myChildren;
  }

  DEFINE_STANDARD_RTTIEXT(TreeModel_ItemProperties, Standard_Transient)

protected:
  //! Initializes the current item. It creates a backup of the specific item information
  Standard_EXPORT void initItem() const;

private:
  TreeModel_ItemBasePtr myItem; //!< current item

  TCollection_AsciiString myKey;         //!< the item key
  Standard_DumpValue      myStreamValue; //!< the stream value
  NCollection_IndexedDataMap<TCollection_AsciiString, Standard_DumpValue>
                                                                   myChildren;  //!< the children
  NCollection_IndexedDataMap<Standard_Integer, TreeModel_RowValue> myRowValues; //!< the values
};

#endif