#include "requirementDetailPanel.h"

#include <wx/statline.h>

using namespace std;
using namespace gui;
//--------------------------------------------------------------
/* Constructor */
RequirementDetailPanel::RequirementDetailPanel(wxWindow *parentWindow, dBus::Bus &bus)
  : wxPanel(parentWindow /*, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER*/)
  , m_bus(bus)
{
  // Initialization

  // Creating controls
  createControls();

  // Post initialization
}
//--------------------------------------------------------------
/* Creating controls */
void RequirementDetailPanel::createControls()
{
  const auto mainPanel = new wxScrolledWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxVSCROLL);
  mainPanel->SetScrollRate(0, 10);     // Set the scroll rate for the panel (vertical only)

  const auto closeButton   = new wxButton(this, wxID_ANY, _("Close"));
  const auto saveButton    = new wxButton(this, wxID_ANY, _("Save"));
  const auto discardButton = new wxButton(this, wxID_ANY, _("Discard"));

  // Controls positioning
  const auto ctrlSizer = new wxBoxSizer(wxVERTICAL);
  ctrlSizer->Add(createControls_metadata(mainPanel), wxSizerFlags(0).Expand().Border(wxALL & ~wxTOP, 5));
  ctrlSizer->Add(createControls_details(mainPanel), wxSizerFlags(0).Expand().Border(wxALL & ~wxTOP, 5));
  ctrlSizer->Add(createControls_classification(mainPanel), wxSizerFlags(0).Expand().Border(wxALL & ~wxTOP & ~wxBOTTOM, 5));
  mainPanel->SetSizer(ctrlSizer);

  const auto buttonSizer = new wxBoxSizer(wxVERTICAL);
  buttonSizer->Add(closeButton, wxSizerFlags(0).Expand());
  buttonSizer->AddStretchSpacer(1);
  buttonSizer->Add(discardButton, wxSizerFlags(0).Expand().Border(wxBOTTOM, 5));
  buttonSizer->Add(saveButton, wxSizerFlags(0).Expand());

  const auto mainSizer = new wxBoxSizer(wxHORIZONTAL);
  mainSizer->Add(mainPanel, wxSizerFlags(1).Expand().Border(wxLEFT | wxRIGHT, 5));
  mainSizer->Add(buttonSizer, wxSizerFlags(0).Expand().Border(wxALL, 5));

  SetSizer(mainSizer);

  // Set the virtual size to match the size of the child panel,
  // enabling scrolling if necessary
  mainPanel->FitInside();

  // Harmonize the sizes of the title controls to ensure they have the same width
  updateTitleSizes();
  Layout();
}
//--------------------------------------------------------------
/* Creating controls for requirement metadata (ID, UUID, name, description, etc.) */
wxSizer *RequirementDetailPanel::createControls_metadata(wxWindow *owner)
{
  const auto uuidTitleCtrl      = createTitle(owner, _T("UUID:"));
  const auto idTitleCtrl        = createTitle(owner, _T("ID:"));
  const auto authorTitleCtrl    = createTitle(owner, _("Author:"));
  const auto createdAtTitleCtrl = createTitle(owner, _("Created at:"));
  const auto updatedAtTitleCtrl = createTitle(owner, _("Updated at:"));

  const auto uuidValueCtrl      = new wxTextCtrl(owner, wxID_ANY);
  const auto idValueCtrl        = new wxTextCtrl(owner, wxID_ANY);
  const auto authorValueCtrl    = new wxTextCtrl(owner, wxID_ANY);
  const auto createdAtValueCtrl = new wxTextCtrl(owner, wxID_ANY);
  const auto updatedAtValueCtrl = new wxTextCtrl(owner, wxID_ANY);

  // Controls positioning
  const auto ctrlSizer = new wxFlexGridSizer(2, 5, 5);
  ctrlSizer->Add(uuidTitleCtrl, wxSizerFlags(0).Expand().CenterVertical());
  ctrlSizer->Add(uuidValueCtrl, wxSizerFlags(1).Expand());
  ctrlSizer->Add(idTitleCtrl, wxSizerFlags(0).Expand().CenterVertical());
  ctrlSizer->Add(idValueCtrl, wxSizerFlags(1).Expand());
  ctrlSizer->Add(authorTitleCtrl, wxSizerFlags(0).Expand().CenterVertical());
  ctrlSizer->Add(authorValueCtrl, wxSizerFlags(1).Expand());
  ctrlSizer->Add(createdAtTitleCtrl, wxSizerFlags(0).Expand().CenterVertical());
  ctrlSizer->Add(createdAtValueCtrl, wxSizerFlags(1).Expand());
  ctrlSizer->Add(updatedAtTitleCtrl, wxSizerFlags(0).Expand().CenterVertical());
  ctrlSizer->Add(updatedAtValueCtrl, wxSizerFlags(1).Expand());
  ctrlSizer->AddGrowableCol(1, 1);

  // Controls positioning
  const auto localSizer = new wxStaticBoxSizer(wxVERTICAL, owner, "Metadata");
  localSizer->Add(ctrlSizer, wxSizerFlags(0).Expand().Border(wxALL, 5));

  return localSizer;
}
//--------------------------------------------------------------
/* Creating controls for requirement details (e.g., custom attributes, child requirements, etc.) */
wxSizer *RequirementDetailPanel::createControls_details(wxWindow *owner)
{
  const auto titleTitleCtrl              = createTitle(owner, _("Title:"));
  const auto descriptionTitleCtrl        = createTitle(owner, _("Description:"));
  const auto acceptanceCriteriaTitleCtrl = createTitle(owner, _("Acceptance criteria:"));

  const auto titleValueCtrl              = new wxTextCtrl(owner, wxID_ANY);
  const auto descriptionValueCtrl        = new wxTextCtrl(owner, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_TAB | wxTE_MULTILINE);
  const auto acceptanceCriteriaValueCtrl = new wxTextCtrl(owner, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_TAB | wxTE_MULTILINE);
  const auto smartCheckBoxCtrl           = new wxCheckBox(owner, wxID_ANY, _("S.M.A.R.T."));

  descriptionValueCtrl->SetMinSize(wxSize(-1, 200));
  acceptanceCriteriaValueCtrl->SetMinSize(wxSize(-1, 100));

  // Controls positioning
  const auto ctrlSizer = new wxFlexGridSizer(2, 5, 5);
  ctrlSizer->Add(titleTitleCtrl, wxSizerFlags(0).Expand().CenterVertical());
  ctrlSizer->Add(titleValueCtrl, wxSizerFlags(1).Expand());
  ctrlSizer->Add(descriptionTitleCtrl, wxSizerFlags(0).Expand());
  ctrlSizer->Add(descriptionValueCtrl, wxSizerFlags(1).Expand());
  ctrlSizer->Add(acceptanceCriteriaTitleCtrl, wxSizerFlags(0).Expand());
  ctrlSizer->Add(acceptanceCriteriaValueCtrl, wxSizerFlags(1).Expand());
  ctrlSizer->AddStretchSpacer();
  ctrlSizer->Add(smartCheckBoxCtrl, wxSizerFlags(1).Expand());
  ctrlSizer->AddGrowableCol(1, 1);

  const auto localSizer = new wxStaticBoxSizer(wxVERTICAL, owner, "Details");
  localSizer->Add(ctrlSizer, wxSizerFlags(0).Expand().Border(wxALL, 5));

  return localSizer;
}
//--------------------------------------------------------------
/* Creating controls for requirement classification (e.g., priority, severity, etc.) */
wxSizer *RequirementDetailPanel::createControls_classification(wxWindow *owner)
{
  const auto typeTitleCtrl     = createTitle(owner, _("Type:"));
  const auto categoryTitleCtrl = createTitle(owner, _("Category:"));
  const auto priorityTitleCtrl = createTitle(owner, _("Priority:"));
  const auto statusTitleCtrl   = createTitle(owner, _("Status:"));

  const auto typeValueCtrl     = new wxTextCtrl(owner, wxID_ANY);
  const auto categoryValueCtrl = new wxTextCtrl(owner, wxID_ANY);
  const auto priorityValueCtrl = new wxTextCtrl(owner, wxID_ANY);
  const auto statusValueCtrl   = new wxTextCtrl(owner, wxID_ANY);

  // Controls positioning
  const auto ctrlSizer = new wxFlexGridSizer(2, 5, 5);
  ctrlSizer->Add(typeTitleCtrl, wxSizerFlags(0).Expand().CenterVertical());
  ctrlSizer->Add(typeValueCtrl, wxSizerFlags(1).Expand());
  ctrlSizer->Add(categoryTitleCtrl, wxSizerFlags(0).Expand().CenterVertical());
  ctrlSizer->Add(categoryValueCtrl, wxSizerFlags(1).Expand());
  ctrlSizer->Add(priorityTitleCtrl, wxSizerFlags(0).Expand().CenterVertical());
  ctrlSizer->Add(priorityValueCtrl, wxSizerFlags(1).Expand());
  ctrlSizer->Add(statusTitleCtrl, wxSizerFlags(0).Expand().CenterVertical());
  ctrlSizer->Add(statusValueCtrl, wxSizerFlags(1).Expand());
  ctrlSizer->AddGrowableCol(1, 1);

  const auto localSizer = new wxStaticBoxSizer(wxVERTICAL, owner, "Classification");
  localSizer->Add(ctrlSizer, wxSizerFlags(0).Expand().Border(wxALL, 5));

  return localSizer;
}
//--------------------------------------------------------------
/* Helper function to create a section title control */
wxStaticText *RequirementDetailPanel::createTitle(wxWindow *owner, const wxString &title)
{
  const auto ctrl = new wxStaticText(owner,
                                     wxID_ANY,
                                     title,
                                     wxDefaultPosition,
                                     wxDefaultSize,
                                     wxST_NO_AUTORESIZE | wxALIGN_RIGHT);
  ctrl->SetFont(GetFont().Italic());

  m_titleControls.push_back(ctrl);

  return ctrl;
}
//--------------------------------------------------------------
/* Harmonize the sizes of the title controls to ensure they have the same width */
void RequirementDetailPanel::updateTitleSizes() const
{
  int maxWidth = 0;
  for (const auto &ctrl : m_titleControls)
  {
    maxWidth = std::max(maxWidth, ctrl->GetSize().GetWidth());
  }
  for (const auto &ctrl : m_titleControls)
  {
    ctrl->SetMinSize(wxSize(maxWidth, -1));
  }
}
//--------------------------------------------------------------
