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

#pragma once

#include "mwdg/mixer/proxy_identifier.hpp"
#include <QAction>
#include <QMenu>
#include <QPointer>
#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::Switches_Pad
{
class Pad;
class Scroll_Area;
} // namespace Wdg::Switches_Pad
namespace MWdg
{
class Inputs_Setup;
} // namespace MWdg
namespace MWdg::Mixer
{
class Setup;
} // namespace MWdg::Mixer
namespace MWdg::Mixer::Switches
{
class Proxies_Model;
}
namespace MWdg::Mixer::Proxy
{
class Group;
}

namespace MWdg::Mixer::Switches
{

/// @brief Mixer
///
class Mixer : public QWidget
{
  Q_OBJECT

  public:
  // -- Construction

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

  ~Mixer ();

  // -- Mixer setup

  const MWdg::Mixer::Setup *
  mixer_setup () const
  {
    return _mixer_setup;
  }

  void
  set_mixer_setup ( const MWdg::Mixer::Setup * setup_n );

  // -- Proxies model

  MWdg::Mixer::Switches::Proxies_Model *
  proxies_model () const
  {
    return _proxies_model;
  }

  void
  set_proxies_model ( MWdg::Mixer::Switches::Proxies_Model * model_n );

  // -- Inputs setup

  const MWdg::Inputs_Setup *
  inputs_setup () const
  {
    return _inputs_setup;
  }

  void
  set_inputs_setup ( const MWdg::Inputs_Setup * setup_n );

  protected:
  // -- Event processing

  bool
  eventFilter ( QObject * watched, QEvent * event ) override;

  private:
  // -- Utiliy

  Q_SLOT
  void
  reload_proxies_groups_begin ();

  Q_SLOT
  void
  reload_proxies_groups_end ();

  // -- Action callbacks

  Q_SLOT
  void
  action_toggle_joined ();

  Q_SLOT
  void
  update_focus_proxies ();

  // -- Gui state

  void
  gui_state_store ();

  void
  gui_state_restore ();

  MWdg::Mixer::Proxy::Group *
  find_visible_proxy ( const MWdg::Mixer::Proxy_Identifier & proxy_id_n );

  // -- Context menu

  bool
  context_menu_start ( const QPoint & pos_n );

  std::size_t
  context_menu_update ();

  Q_SLOT
  void
  context_menu_update_visible ();

  private:
  // -- Attributes
  const MWdg::Mixer::Setup * _mixer_setup = nullptr;
  MWdg::Mixer::Switches::Proxies_Model * _proxies_model = nullptr;
  const MWdg::Inputs_Setup * _inputs_setup = nullptr;

  std::vector< Wdg::Pad_Proxy::Group * > _proxies_groups_pass;

  std::unique_ptr< Wdg::Switches_Pad::Scroll_Area > _switches_area;
  std::unique_ptr< Wdg::Switches_Pad::Pad > _switches_pad;

  // Action focus proxy
  QPointer< MWdg::Mixer::Proxy::Group > _act_proxies_group;
  unsigned int _act_proxies_column;

  // GUI state
  MWdg::Mixer::Proxy_Identifier _proxy_id;

  // Context menu
  QMenu _cmenu;
  QAction _act_toggle_joined;
};

} // namespace MWdg::Mixer::Switches
