/***************************************************************************

    source::worx xtree
    Copyright © 2024-2025 c.holzheuer
    christoph.holzheuer@gmail.com

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

***************************************************************************/


#ifndef XQITEM_H
#define XQITEM_H

#include <QtQmlIntegration>
#include <QVariant>
#include <QVector>
#include <QStandardItem>

#include <xqnode.h>


using XQItemList = QList<QStandardItem*>;

class XQItemFactory;
class XQItemType;

/**
 * @brief Extends QStandardItem to hold additional
 * settings.
 */

class XQItem : public QStandardItem
{

  QML_ELEMENT

  friend class XQItemFactory;

public:

  /// Die data(enum role) Infrastruktur wird sowohl für XQItem als auch
  /// für den XQItemType verwendet, deshalb definieren wir hier _alle_
  /// notwendigen Roles

  enum ItemDataRole
  {
    NoRole = Qt::UserRole + 1,
    // das ist ein pointer auf den  original-string aus dem XML
    ContentRole,
    ItemTypeRole,
    RenderStyleRole,
    EditorTypeRole,
    UnitTypeRole,
    ContentFormatRole,
    // @see qstandarditemmodel.cpp, stolen from there
    FlagsRole = Qt::ItemDataRole(Qt::UserRole - 1),
    IconRole = Qt::DecorationRole,
    // re-start count
    FixedChoicesRole = ContentFormatRole+1,
    ContentNodeRole,
    //?? werden beide gebraucht?
    SheetNodeRole,
    // das ist der Schlüssel um den content string aus dem contentNode zu holen
    //ContentKeyRole,
    // weitere, weniger gebräuchlichen Rollen für XQItemType::data()

    TypeKeyRole,
    //TypeNameRole, nicht so wichtig
    RoleEnd
  };

  // wie wirds gemalt
  enum RenderStyle
  {
    NoRenderStyle,
    HiddenStyle,
    HeaderStyle,
    PlainStyle,
    CheckBoxStyle,
    ComboBoxStyle,
    PickerStyle,
    SpinBoxStyle,
    ColorBarStyle,
    FormattedStyle,
    TreeHeaderStyle,
    CustomRenderStyle,    
    RenderStyleEnd    //!< Not a special editor. Keep at end of this enumeration!
    // ...
  };

  // wie wirds editiert
  enum EditorType
  {
    NoEditorType,
    LineEditType,
    ComboBoxType,
    PickerType,
    ColorBarType,
    SpinBoxType,
    CustomEditorType,
    EditorTypeEnd
  };

  // typische Einheiten
  enum UnitType
  {
    NoUnitType,
    Ampere,
    Volt,
    Ohm,
    Watt,
    WattPeak,
    WattHour,
    Farad,
    Tesla,
    Henry,
    Hertz,
    Coulomb,
    Kelvin,
    Percent,
    Second,
    Meter,
    Kg,
    ISODate,
    UnitTypeEnd
  };


  XQItem();
  XQItem( XQItemType* itemType );
  XQItem( XQItemType* itemType, const QString* content );
  XQItem( XQItemType* itemType, const QString& content );

  virtual ~XQItem() = default;

  //! creates not a clone but a new default item, \see  QStandardItemModel::setItemPrototype()
  //! -- not used at the moment --
  XQItem* clone() const override;

  //! __fix Tested, ob ein itemtype vorhanden ist.
  bool isValidX() const;

  bool      hasContentNode() const;
  //! gibt den zu diesem item gehörigen datenknoten zurück
  XQNodePtr contentNode() const;


  XQNodePtr sheetNode() const;
  void      setSheetNode( const XQNodePtr& sheetNode );

  XQItemType&      itemType() const;
  void             setItemType( XQItemType* itemTypePtr );

  // shortcuts für die itemFlags
  // __fix! das können die selber !?
  void             addFlag( Qt::ItemFlag newFlag );
  void             clearFlag( Qt::ItemFlag newFlag );
  QString          itemFlagsToString() const;

  // das ist die EditRole: unformatierter Text
  QString         rawText() const;

  // changed: gibt jetzt den  pointer zurück.
  //QString*        content() const;
  //void            setContent( const QString* content );

  //
  // Convenience-Funktionen zum Memberzugriff, die Implementierung
  // läuft über die data()-Methode wie in den QStandardItems. So
  // ist sie für XQItem und auch für XQItemType als Deirvat von XQItem gültig.
  //

  RenderStyle     renderStyle() const;
  QString         renderStyleToString() const;
  void            setRenderStyle(RenderStyle renderStyle );

  EditorType      editorType() const;
  QString         editorTypeToString() const;
  void            setEditorType(EditorType editorType);

  UnitType        unitType() const;
  QString         unitTypeToString() const;
  void            setUnitType(UnitType unitType);

  QString         contentFormat() const;
  void            setContentFormat(const QString& contentFormat);
  QStandardItemModel* fixedChoices() const;

  QString         fixedChoicesToString() const;

  //! setzt das auswahl-model für read-only comboboxes
  void            setfixedChoices( QStandardItemModel* newModel );

  //
  //shortCuts
  //

  bool           isHeaderStyle();
  QString        dataRoleName(int role) const;

  QVariant       data(int role = Qt::DisplayRole ) const override;
  void           setData(const QVariant &value, int role ) override;

  /*
  template<typename T>
  void setToVariant(T entry, QtExtUserRoles::NTDataRoles role)
  {
    setData(QVariant::fromValue<T>(entry), role);
  }

  template<typename T>
  T getFromVariant(QtExtUserRoles::NTDataRoles role)
  {
    return data(role).value<T>();
  }
  */


  ///
  /// Static convenience methods
  ///

  static QVariant      makeVariant( XQItem* item, int dataRole, const QString& source );

  static XQItem&       xqItemFromIndex( const QModelIndex& index );
  static XQItem&       fallBackDummyItem();

  static int           fetchItemDataRole( const QString& dataRoleKey );
  static QString       fetchItemDataRoleName( int dataRole );
  static Qt::ItemFlag  fetchItemFlag( const QString& flagKey );
  static QString       fetchItemFlagName( int flag );
  static RenderStyle   fetchRenderStyle( const QString& styleKey );
  static QString       fetchRenderStyleToString( RenderStyle renderStyle );
  static EditorType    fetchEditorType( const QString& editorTypeKey );
  static QString       fetchEditorTypeToString( EditorType editorType );
  static UnitType      fetchUnitType( const QString& typeKey );
  static QString       fetchUnitTypeToString( UnitType );

protected:

  XQItem(const XQItem& other) = default;
  XQItem& operator=(const XQItem& other) = default;

  bool    hasContentPtr() const;
  QString contentFallBackText() const;

  // das ist protected, weil damit der content()-zugriff demoliert werden kann
  void setContentNode(const XQNodePtr& contentNode );

  using XQItemFlagMap       = QMap<QString,int>;
  using XQItemDataRoleMap   = QMap<QString,int>;
  using XQRenderStyleMap    = QMap<QString,RenderStyle>;
  using XQEditorTypeMap     = QMap<QString,EditorType>;
  using XQUnitTypeMap       = QMap<UnitType, QString>;
  using XQPrefixExponentMap = QMap<QString, int>;

  static XQItemFlagMap       s_ItemFlagMap;
  static XQItemDataRoleMap   s_ItemDataRoleMap;
  static XQRenderStyleMap    s_RenderStyleMap;
  static XQEditorTypeMap     s_EditorTypeMap;
  static XQUnitTypeMap       s_UnitTypeMap;
  static XQPrefixExponentMap s_PrefixExponentMap;

  //! leerer itemtype als mockup für den xqitem default constructor
  static XQItemType          s_DummyItemType;

};

Q_DECLARE_METATYPE(XQItem);
Q_DECLARE_METATYPE(XQItem::RenderStyle);
Q_DECLARE_METATYPE(XQItem::EditorType);
Q_DECLARE_METATYPE(XQItem::UnitType);
Q_DECLARE_METATYPE(const QString*);

#endif // XQITEM_H






