/// QasTools: Desktop toolset for the Linux sound system ALSA.
/// \copyright See COPYING file.

#pragma once

#include "wdg/pad_focus_info.hpp"
#include <QWidget>
#include <memory>
#include <vector>

// Forward declaration
namespace dpe
{
class Image_Allocator;
}
namespace Wdg
{
class Style_Db;
} // namespace Wdg
namespace Wdg::Pad_Proxy
{
class Group;
}
namespace Wdg::Sliders_Pad
{
class Data;
class Data_Group;
class Data_Column;
class Footer;
class Header_Data;
class Header;
class Style;
} // namespace Wdg::Sliders_Pad

namespace Wdg::Sliders_Pad
{

/// @brief Sliders pad
///
class Pad : public QWidget
{
  Q_OBJECT

  public:
  // -- Construction

  Pad ( const Wdg::Style_Db * style_db_n,
        dpe::Image_Allocator * image_alloc_n,
        QWidget * parent_n = nullptr );

  ~Pad ();

  // -- Proxies groups list

  const std::vector< Wdg::Pad_Proxy::Group * > &
  proxies_groups () const
  {
    return _proxies_groups;
  }

  void
  set_proxies_groups ( const std::vector< Wdg::Pad_Proxy::Group * > & list_n );

  void
  clear_proxies_groups ();

  // -- Proxies group access

  std::size_t
  num_proxies_groups () const
  {
    return _proxies_groups.size ();
  }

  Wdg::Pad_Proxy::Group *
  proxies_group ( std::size_t idx_n )
  {
    return _proxies_groups[ idx_n ];
  }

  // -- Widget style database

  const Wdg::Style_Db *
  style_db () const
  {
    return _style_db;
  }

  // -- Image_Set_Group allocator

  dpe::Image_Allocator *
  image_alloc () const
  {
    return _image_alloc;
  }

  // -- Show footer

  bool
  footer_visible () const;

  void
  set_footer_visible ( bool flag_n );

  // -- Wheel degrees

  std::size_t
  wheel_degrees () const
  {
    return _wheel_degrees;
  }

  void
  set_wheel_degrees ( std::size_t delta_n );

  // Widgets

  QWidget *
  header ();

  QWidget *
  footer ();

  Header *
  header_cast ();

  Footer *
  footer_cast ();

  Header_Data *
  header_data ();

  Header_Data *
  footer_data ();

  std::size_t
  num_widgets () const
  {
    return _widgets.size ();
  }

  QWidget *
  widget ( std::size_t idx_n )
  {
    return _widgets[ idx_n ].get ();
  }

  // -- Focus info

  const Pad_Focus_Info &
  focus_info () const
  {
    return _focus_info;
  }

  /// @brief Event handler reimplementation
  bool
  event ( QEvent * event_n ) override;

  // -- Public signals
  Q_SIGNAL
  void
  sig_focus_changed ();

  Q_SIGNAL
  void
  sig_footer_label_selected ( unsigned int group_idx_n,
                              unsigned int column_idx_n );

  // -- Public slots
  Q_SLOT
  bool
  set_focus_proxy ( unsigned int group_idx_n );

  Q_SLOT
  bool
  set_focus_proxy ( unsigned int group_idx_n,
                    unsigned int column_idx_n,
                    unsigned int row_idx_n );

  protected:
  // -- Protected methods

  void
  clear_widgets ();

  void
  create_widgets ();

  // Event methods

  void
  changeEvent ( QEvent * event_n ) override;

  void
  resizeEvent ( QResizeEvent * event ) override;

  void
  paintEvent ( QPaintEvent * event ) override;

  protected:
  // -- Protected slots

  Q_SLOT
  void
  header_label_selected ( unsigned int group_idx_n, unsigned int column_idx_n );

  Q_SLOT
  void
  footer_label_selected ( unsigned int group_idx_n, unsigned int column_idx_n );

  Q_SLOT
  void
  style_palette_changed ( unsigned int style_id_n );

  private:
  // -- Private methods

  void
  update_colors ();

  private:
  // -- Attributes
  std::vector< Wdg::Pad_Proxy::Group * > _proxies_groups;
  std::unique_ptr< Data > _sp_data;

  std::vector< std::unique_ptr< QWidget > > _widgets;
  Wdg::Pad_Focus_Info _focus_info;

  bool _update_decoration = true;

  std::size_t _wheel_degrees = 720;

  std::unique_ptr< Style > _sp_style; // Paints decoration graphics
  const Wdg::Style_Db * _style_db = nullptr;
  dpe::Image_Allocator * _image_alloc = nullptr;
};

} // namespace Wdg::Sliders_Pad
