/* +------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)            |
   |                          https://www.mrpt.org/                         |
   |                                                                        |
   | Copyright (c) 2005-2024, Individual contributors, see AUTHORS file     |
   | See: https://www.mrpt.org/Authors - All rights reserved.               |
   | Released under BSD License. See: https://www.mrpt.org/License          |
   +------------------------------------------------------------------------+ */
#pragma once

#include <mrpt/config/CConfigFileBase.h>
#include <mrpt/config/CConfigFileMemory.h>
#include <mrpt/gui/keycodes.h>
#include <mrpt/img/CImage.h>
#include <mrpt/system/string_utils.h>  // firstNLines()

#if MRPT_HAS_WXWIDGETS

#include <wx/app.h>
#include <wx/artprov.h>
#include <wx/bitmap.h>
#include <wx/busyinfo.h>
#include <wx/button.h>
#include <wx/checkbox.h>
#include <wx/choice.h>
#include <wx/colordlg.h>
#include <wx/dc.h>
#include <wx/dcclient.h>
#include <wx/dcmemory.h>
#include <wx/dirdlg.h>
#include <wx/filedlg.h>
#include <wx/frame.h>
#include <wx/image.h>
#include <wx/imaglist.h>
#include <wx/intl.h>
#include <wx/log.h>
#include <wx/menu.h>
#include <wx/msgdlg.h>
#include <wx/notebook.h>
#include <wx/panel.h>
#include <wx/pen.h>
#include <wx/progdlg.h>
#include <wx/radiobox.h>
#include <wx/settings.h>
#include <wx/sizer.h>
#include <wx/spinctrl.h>
#include <wx/statbmp.h>
#include <wx/stattext.h>
#include <wx/statusbr.h>
#include <wx/string.h>
#include <wx/textctrl.h>
#include <wx/textdlg.h>
#include <wx/timer.h>
#include <wx/toolbar.h>

#endif

#include <mutex>

namespace mrpt
{
namespace gui
{
/** \addtogroup mrpt_gui_wxutils Utilities for MRPT-wxWidgets interfacing (in
  #include <mrpt/gui/WxUtils.h>)
  * \ingroup mrpt_gui_grp
  * @{ */
#if MRPT_HAS_WXWIDGETS

/** Returns the size of a window, including the optional magnification scale set
 * by users in Display->Appearance.
 */
wxSize GetScaledClientSize(const wxWindow* w);

#ifndef WX_START_TRY

#define WX_START_TRY \
  try                \
  {
#define WX_END_TRY                                                                           \
  }                                                                                          \
  catch (std::exception & e)                                                                 \
  {                                                                                          \
    const size_t maxLines = 7;                                                               \
    const std::string sErr = mrpt::system::firstNLines(mrpt::exception_to_str(e), maxLines); \
    std::cerr << e.what() << std::endl;                                                      \
    wxMessageBox(sErr, wxT("Exception"), wxOK, nullptr);                                     \
  }                                                                                          \
  catch (...) { wxMessageBox(_("Untyped exception!"), _("Exception"), wxOK, nullptr); }

#endif

/** Create a wxImage from a MRPT image. The new object must be freed by the user
 * when not required anymore.
 * \sa MRPTImage2wxImage
 */
wxImage* MRPTImage2wxImage(const mrpt::img::CImage& img);

/** Create a wxBitmap from a MRPT image. The new object must be freed by the
 * user when not required anymore.
 * \sa MRPTImage2wxImage
 */
wxBitmap* MRPTImage2wxBitmap(const mrpt::img::CImage& img);

/** Create a MRPT image from a wxImage. The new object must be freed by the user
 * when not required anymore.
 *  It is recommended to use wxImage2MRPTImagePtr instead since smart pointers
 * are safer to manage.
 * \sa wxImage2MRPTImage, wxImage2MRPTImagePtr
 */
mrpt::img::CImage* wxImage2MRPTImage(const wxImage& img);

/** Create a MRPT image from a wxImage. The new object is returned as a smart
 * pointer to a CImage object.
 * \sa wxImage2MRPTImage
 */
mrpt::img::CImage::Ptr wxImage2MRPTImagePtr(const wxImage& img);

/** Extracts the key modifiers from a wxKeyEvent */
mrptKeyModifier keyEventToMrptKeyModifier(const wxKeyEvent& ev);

/** A custom control to display the bitmap and avoid flicker
 */
class wxMRPTImageControl : public wxPanel
{
 protected:
  wxBitmap* m_img;
  std::mutex m_img_cs;

  wxPoint m_last_mouse_point, m_last_mouse_click;
  std::mutex m_mouse_cs;

 public:
  wxMRPTImageControl(wxWindow* parent, wxWindowID winID, int x, int y, int width, int height);
  ~wxMRPTImageControl() override;

  /** Assigns this image. This object has the ownship of the image and will
   * delete it when appropriate. Remember to call Refresh to display the
   * image. */
  void AssignImage(wxBitmap* img);
  /** Assigns this image. Remember to call Refresh to display the image. */
  void AssignImage(const mrpt::img::CImage& img);
  void GetBitmap(wxBitmap& bmp);

  void OnPaint(wxPaintEvent& ev);
  void OnMouseMove(wxMouseEvent& ev);
  void OnMouseClick(wxMouseEvent& ev);

  void OnEraseBackground(wxEraseEvent&)
  { /* Do nothing */
  }
};
// end wxMRPTImageControl  -----------

/** A panel to select the camera input from all the formats supported by MRPT */
class CPanelCameraSelection : public wxPanel
{
 public:
  CPanelCameraSelection(wxWindow* parent, wxWindowID id = wxID_ANY);
  ~CPanelCameraSelection() override;

  void readConfigIntoVideoSourcePanel(
      const std::string& sect, const mrpt::config::CConfigFileBase* cfg) const;

  void writeConfigFromVideoSourcePanel(
      const std::string& sect, mrpt::config::CConfigFileBase* cfg) const;

  //(*Declarations(CPanelCameraSelection)
  wxTextCtrl* edRawlogLabel;
  wxStaticText* StaticText10;
  wxStaticText* StaticText9;
  wxPanel* Panel5;
  wxButton* btnBrowseRawlogDir;
  wxRadioBox* rbBumblebeeSel;
  wxButton* btnBrowseVideo;
  wxStaticText* StaticText2;
  wxPanel* Panel4;
  wxCheckBox* cbKinect_3D;
  wxRadioBox* rbKinect_int;
  wxCheckBox* cbSR_chConf;
  wxStaticText* StaticText6;
  wxSpinCtrl* opencvCamIndex;
  wxTextCtrl* edIPcamURL;
  wxStaticText* StaticText8;
  wxStaticText* StaticText11;
  wxTextCtrl* edCustomCamConfig;
  wxTextCtrl* edSR_IP;
  wxPanel* Panel1;
  wxChoice* cbOpencvCamType;
  wxStaticText* StaticText1;
  wxStaticText* StaticText3;
  wxRadioBox* rbSR_usb;
  wxPanel* Panel6;
  wxButton* btnBrowseRawlog;
  wxPanel* Panel3;
  wxCheckBox* cbGrayscale;
  wxCheckBox* cbSR_chRange;
  wxStaticText* StaticText5;
  wxStaticText* StaticText7;
  wxPanel* pnKinect;
  wxTextCtrl* edVideoFile;
  wxCheckBox* cbBumblebeeRectif;
  wxCheckBox* cbKinect_Int;
  wxCheckBox* cbSR_chIntensity;
  wxCheckBox* cbKinect_Depth;
  wxNotebook* pagesCameras;
  wxPanel* pnSwissRanger;
  wxTextCtrl* edRawlogFile;
  wxTextCtrl* edRawlogImgDir;
  wxPanel* Panel2;
  wxCheckBox* cbSR_ch3D;
  wxStaticText* StaticText4;
  wxChoice* cbOpencvResolution;
  //*)

 protected:
  //(*Identifiers(CPanelCameraSelection)
  static const long ID_STATICTEXT1;
  static const long ID_SPINCTRL1;
  static const long ID_STATICTEXT3;
  static const long ID_CHOICE1;
  static const long ID_STATICTEXT6;
  static const long ID_CHOICE2;
  static const long ID_PANEL2;
  static const long ID_STATICTEXT7;
  static const long ID_TEXTCTRL1;
  static const long ID_PANEL3;
  static const long ID_TEXTCTRL6;
  static const long ID_PANEL4;
  static const long ID_STATICTEXT8;
  static const long ID_TEXTCTRL2;
  static const long ID_BUTTON7;
  static const long ID_PANEL5;
  static const long ID_STATICTEXT9;
  static const long ID_TEXTCTRL3;
  static const long ID_BUTTON8;
  static const long ID_STATICTEXT5;
  static const long ID_TEXTCTRL7;
  static const long ID_BUTTON9;
  static const long ID_STATICTEXT10;
  static const long ID_TEXTCTRL8;
  static const long ID_STATICTEXT11;
  static const long ID_PANEL6;
  static const long ID_RADIOBOX1;
  static const long ID_CHECKBOX1;
  static const long ID_STATICTEXT2;
  static const long ID_PANEL7;
  static const long ID_RADIOBOX2;
  static const long ID_STATICTEXT4;
  static const long ID_TEXTCTRL4;
  static const long ID_CHECKBOX3;
  static const long ID_CHECKBOX4;
  static const long ID_CHECKBOX5;
  static const long ID_CHECKBOX6;
  static const long ID_PANEL1;
  static const long ID_CHECKBOX7;
  static const long ID_CHECKBOX8;
  static const long ID_CHECKBOX9;
  static const long ID_RADIOBOX3;
  static const long ID_PANEL8;
  static const long ID_NOTEBOOK1;
  static const long ID_CHECKBOX2;
  //*)

 private:
  //(*Handlers(CPanelCameraSelection)
  //*)
  void OnbtnBrowseVideoClick(wxCommandEvent& event);
  void OnbtnBrowseRawlogClick(wxCommandEvent& event);
  void OnbtnBrowseRawlogDirClick(wxCommandEvent& event);

  DECLARE_EVENT_TABLE()
};
// end   -----------

/** Auxiliary structures used internally to mrpt */
namespace detail
{
struct TReturnAskUserOpenCamera
{
  std::string selectedConfig;
  bool accepted_by_user;
};
}  // namespace detail

#endif
/** @} */
}  // namespace gui
}  // namespace mrpt
