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

    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 XQVIEWMODEL_H
#define XQVIEWMODEL_H

#include <QUndoStack>
#include <QMenu>
#include <QStandardItemModel>
#include <QAbstractItemView>
#include <QtQmlIntegration>

#include <xqsimpleclipboard.h>
#include <xqsectionmanager.h>
#include <xqitemfactory.h>
#include <xqcontextmenu.h>


class XQTreeTable;
class XQItem;
class XQCommand;


//! ein erweitertes QStandardItemModel welches 'seine' view bereits enthält.

class XQViewModel : public QStandardItemModel
{
  Q_OBJECT
  QML_ELEMENT

public:

  XQViewModel(QObject* parent = nullptr);
  virtual ~XQViewModel() = default;

   QHash<int, QByteArray> roleNames() const override;

  XQTreeTable* treeTable();
  virtual void setTreeTable( XQTreeTable* mainView );

  QUndoStack* undoStack();
  void setUndoStack( QUndoStack* undoStack );

  virtual void initModel( const QString& modelName);

  void expandNewItem(const QModelIndex& index);
  void toggleSection( const XQModelSection& section );

  //little helpers
  const XQItem& xqRootItem();
  XQNodePtr contentRootNode();

  XQItem&       xqItemFromIndex(const QModelIndex& index) const;
  XQItem&       xqFirstItem(int row) const;

  // undo-/redo-able stuff

  virtual void cmdToggleSection( const XQCommand& command );
  virtual void cmdCut( const XQCommand& command );
  virtual void cmdCutUndo( const XQCommand& command );
  virtual void cmdPaste( const XQCommand& command );
  virtual void cmdPasteUndo( const XQCommand& command );
  virtual void cmdDelete( const XQCommand& command );
  virtual void cmdDeleteUndo( const XQCommand& command );
  virtual void cmdNew( const XQCommand& command );
  virtual void cmdNewUndo( const XQCommand& command );

  // Derzeit wird die default-implementierung von data/setData genutzt. hier wäre dann die
  // Stelle um setData & data an externe 'handler' umzubiegen, siehe giovannies 'model-injection'

signals:

  void xqItemChanged( const XQItem& item );
  void itemCreated( XQItem* newItem );
  void sectionCreated( const XQModelSection& section );
  void sectionToggled( const XQModelSection& section );

public slots:

  virtual void onShowContextMenu(const QPoint& point);
  virtual void onActionTriggered(QAction* action);
  virtual void onToggleSection(const QString& sectionKey );
  // handle XQCommands ( == UndoCommand )
  virtual void onCommandRedo( const XQCommand& command );
  virtual void onCommandUndo( const XQCommand& command );

protected:

  void addSection(const XQItemList& list, const XQNodePtr& sheetNode );
  virtual void initContextMenu() = 0;
  // __fixme: should be created from xml
  virtual void setupViewProperties();

protected:

  using MemCall    = void (XQViewModel::*)(const XQCommand&);
  using MemCallMap = QMap<XQCommand::CmdType,MemCall>;

  // das eine reference auf ein globales singleton
  XQItemFactory&    _itemFactory;
  XQSimpleClipBoard _clipBoard;
  XQSectionManager  _sections;

  XQTreeTable*      _treeTable{};
  //QAbstractItemView* _treeTable{};
  QUndoStack*       _undoStack{};
  XQContextMenu*    _contextMenu{};

  //! Die Modelbeschreibung
  XQNodePtr      _modelSheet{};
  //! Der eigentliche Inhalt
  XQNodePtr      _contentRoot{};

};

#endif // XQVIEWMODEL_H
