#include "stdafx.h"

#include "xtr/dialog/EditConstituenta.h"

#include "resource.h"

#include "xtr/Exteor.h"

#include "xtr/ui/UIHelper.h"

namespace xtr::dialog {

using ui::Keyboard;

#pragma warning( push )
#pragma warning( disable : 26440 26436 26454 )

BEGIN_MESSAGE_MAP(EditConstituentaDlg, CPropertySheet)
  ON_WM_INITMENUPOPUP()

  ON_COMMAND_EX(IXTRC_INSERT_BASE_SET, &ThisClass::OnInsertCst)
  ON_COMMAND_EX(IXTRC_INSERT_CONST_SET, &ThisClass::OnInsertCst)
  ON_COMMAND_EX(IXTRC_INSERT_RS, &ThisClass::OnInsertCst)
  ON_COMMAND_EX(IXTRC_INSERT_AXIOM, &ThisClass::OnInsertCst)
  ON_COMMAND_EX(IXTRC_INSERT_TERM, &ThisClass::OnInsertCst)
  ON_COMMAND_EX(IXTRC_INSERT_THEOREMA, &ThisClass::OnInsertCst)
  ON_COMMAND_EX(IXTRC_INSERT_FUNCTION, &ThisClass::OnInsertCst)
  ON_COMMAND_EX(IXTRC_INSERT_PREDICATE, &ThisClass::OnInsertCst)

  XTR_COMMAND_UPD(IXTRC_AUTOCHECK)
  XTR_COMMAND_UPD(IXTRC_EDITREF)
  XTR_COMMAND_UPD(IXTRC_RSNAVIGATOR)
END_MESSAGE_MAP()

#pragma warning( pop )

EditConstituentaDlg::EditConstituentaDlg(doc::RSFacade& editor, const EntityUID activeUID, CWnd* pParentWnd)
  : CPropertySheet(IXTRS_EDITING_CST, pParentWnd), activeUID{ activeUID }, editor{ &editor } {
  m_CstPage = std::make_unique<CstDataPage>(*this);
  m_ModelPage = std::make_unique<RSModelPage>(*this);
  AddPage(m_CstPage.get());
  if (editor.IsModel()) {
    AddPage(m_ModelPage.get());
  }
}

EditConstituentaDlg::~EditConstituentaDlg() = default;

BOOL EditConstituentaDlg::OnInitDialog() {
  CPropertySheet::OnInitDialog();

  CreateMenu();
  FixWindowSize();
  return TRUE;
}

void EditConstituentaDlg::CreateMenu() {
  m_Menu = std::make_unique<CMenu>();
  m_Menu->LoadMenuW(IXTRAD_MENU_CST);
  SetMenu(m_Menu.get());
}

void EditConstituentaDlg::FixWindowSize() {
  auto rect = ui::WindowRect(*this);
  rect.bottom += GetSystemMetrics(SM_CYMENU);
  MoveWindow(rect);
}

void EditConstituentaDlg::StepNext() {
  auto iter = editor->List().Find(activeUID);
  assert(iter != std::end(editor->List()));

  ++iter;
  if (iter != std::end(editor->List())) {
    activeUID = *iter;
  }
}

void EditConstituentaDlg::StepPrev() {
  auto iter = editor->List().Find(activeUID);
  assert(iter != std::end(editor->List()));

  if (iter != std::begin(editor->List())) {
    --iter;
    activeUID = *iter;
  }
}

BOOL EditConstituentaDlg::PreTranslateMessage(MSG* pMsg) {
  if (pMsg->message == WM_KEYDOWN) {
    const auto key = pMsg->wParam;
    if (IsControlAndSPressed(key)) {
      if (!GetActivePage()->OnApply()) {
        editor->Document().DoFileSave();
      }
      return TRUE;
    }
    if (IsControlAndEnterPressed(key)) {
      GetActivePage()->OnOK();
      EndDialog(IDOK);
      return TRUE;
    }
  }
  return CPropertySheet::PreTranslateMessage(pMsg);
}

BOOL EditConstituentaDlg::IsControlAndSPressed(const WPARAM& key) noexcept {
  return key == 'S' &&
    Keyboard::IsPressed(VK_CONTROL) &&
    !Keyboard::IsPressed(VK_SHIFT);
}

BOOL EditConstituentaDlg::IsControlAndEnterPressed(const WPARAM& key) noexcept {
  return key == VK_RETURN &&
    Keyboard::IsPressed(VK_CONTROL) &&
    !Keyboard::IsPressed(VK_SHIFT);
}

void EditConstituentaDlg::OnInitMenuPopup(CMenu* pMenu, uint32_t /*nIndex*/, BOOL bSysMenu) {
  if (!bSysMenu) {
    UpdateMenuState(*pMenu);
  }
}

void EditConstituentaDlg::UpdateMenuState(CMenu& menu) {
  static constexpr auto VALID_MENU_LIMIT = 0xF000;
  CCmdUI state{};
  state.m_pMenu = &menu;
  state.m_nIndexMax = menu.GetMenuItemCount();
  for (state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax; ++state.m_nIndex) {
    state.m_nID = menu.GetMenuItemID(state.m_nIndex);
    if (state.m_nID != 0) {
      state.m_pSubMenu = nullptr;
      state.DoUpdate(this, state.m_nID < VALID_MENU_LIMIT);
    }
  }
}

#pragma warning( push )
#pragma warning( disable : 26440) // Note: ignore noexcept suggestion for macro used MFC function

BOOL EditConstituentaDlg::OnCommandRun(const uint32_t command) { // NOLINT(readability-convert-member-functions-to-static)
  switch (command) {
  default: return TRUE;
  case IXTRC_AUTOCHECK: {
    XTROptions::ParseRSL().autoCheck = !XTROptions::ParseRSL().autoCheck;
    break;
  }
  case IXTRC_EDITREF: {
    XTROptions::Text().editReference = !XTROptions::Text().editReference;
    break;
  }
  case IXTRC_RSNAVIGATOR: {
    XTROptions::ParseRSL().enableNavigator = !XTROptions::ParseRSL().enableNavigator;
    break;
  }
  }
  return TRUE;
}

#pragma warning( pop )

BOOL EditConstituentaDlg::OnInsertCst(const uint32_t /*command*/) {
  UpdateData();
  return FALSE;
}

void EditConstituentaDlg::OnUpdateCommandUI(CCmdUI* pCmdUI) { // NOLINT(readability-convert-member-functions-to-static)
  pCmdUI->Enable();
  switch(pCmdUI->m_nID)  {
  default: break;
  case IXTRC_AUTOCHECK: pCmdUI->SetCheck(XTROptions::ParseRSL().autoCheck);    break;
  case IXTRC_EDITREF: pCmdUI->SetCheck(XTROptions::Text().editReference);    break;
  case IXTRC_RSNAVIGATOR: pCmdUI->SetCheck(XTROptions::ParseRSL().enableNavigator);   break;
  }
}

} // namespace xtr::dialog