#pragma once

#include "RSListCtrl.h"
#include "xtr/doc/RSFacade.h"

namespace xtr::ui {

//! Control: Table of constituents for RSFormDoc and RSModelDoc
class RSTableCtrl final : public RSListCtrl {
  struct SchemaHeader;
  struct ModelHeader;

public:
  enum ViewMode {  MODE_RSFORM = 1, MODE_RSMODEL, };

private:
  doc::RSFacade* editor{ nullptr };
  ccl::SetOfEntities selection{};

  BOOL disableReentrance{ FALSE };

  struct DnD {
    BOOL active{ FALSE };

    int32_t dragFrom{};
    std::optional<int32_t> dragTo{};
    CWnd* source{ nullptr };
    CWnd* destination{ nullptr };
  };
  DnD dnd{};

  CToolTipCtrl tooltips{};

public:
  [[nodiscard]] BOOL IsInit() const noexcept {
    return editor != nullptr;
  }
  void Init(doc::RSFacade& doc);
  void Update(BOOL updateSelection = FALSE);

  [[nodiscard]] const ccl::SetOfEntities& Selection() const noexcept {
    return selection;
  }
  void Select(EntityUID uid, BOOL bClearSelection = FALSE);
  void SelectMultiple(const ccl::SetOfEntities& selList);
  void EnsureVisibleCst(EntityUID uid);
  void ResetColumns();

  [[nodiscard]] std::optional<EntityUID> UIDForIndex(int nItem) const;
  [[nodiscard]] std::optional<int32_t> IndexForUID(EntityUID uid) const;

  [[nodiscard]] BOOL IsCommandActive(uint32_t command) const noexcept;
  BOOL RunCommand(uint32_t command);

private:
  BOOL PreTranslateMessage(MSG *pMsg) override;

DECLARE_MESSAGE_MAP()
  afx_msg void OnDestroy();
  afx_msg void OnMouseMove(uint32_t nFlags, CPoint point);
  afx_msg void OnLButtonUp(uint32_t nFlags, CPoint point);
  afx_msg BOOL OnBegindragConstituenta(NMHDR *pNMHDR, LRESULT *result);
  afx_msg BOOL OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *result);
  afx_msg BOOL OnDblclkConstituenta(NMHDR *pNMHDR, LRESULT *result);
  afx_msg BOOL OnSelectChange(NMHDR *pNMHDR, LRESULT *result);

private:
  void InitToolTips();
  void InitHeaders();

  void InsertCst(EntityUID target);
  void InputCstData(int32_t nItem, EntityUID target);
  void UpdateSelList();

  void ResetHighlightScroll();
  void UpdateHighlightScroll(CPoint cursorPos);
  void DrawSingleCell(NMLVCUSTOMDRAW* device);

  void PasteFromClipboard();
  ccl::VectorOfEntities InsertClipboard();
  void MoveUp();
  void MoveDown();

  void ActivateCst();
  void MoveSelectedBefore(int32_t index);

  static BOOL ProcessDrawStages(const NMLVCUSTOMDRAW* device, LRESULT* result) noexcept;
};

} // namespace xtr::ui