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

#pragma once

#include "tray/shared.hpp"
#include <QIcon>
#include <QObject>
#include <array>
#include <memory>

// Forward declaration
namespace Tray
{
class Icon;
class Notifier;
class Setup;
} // namespace Tray
namespace QSnd
{
class Card_Info;
class Cards_Db;
} // namespace QSnd
namespace QSnd::Mixer
{
class Elem;
class Mixer;
} // namespace QSnd::Mixer
namespace MWdg
{
class Mixer_Device_Setup;
}

namespace Tray
{

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

  public:
  // -- Construction

  Mixer ( const Tray::Setup * setup_n,
          const MWdg::Mixer_Device_Setup * mixer_device_setup_n,
          QSnd::Cards_Db * cards_db_n,
          QObject * parent_n = nullptr );

  ~Mixer () override;

  // -- State

  bool
  is_visible () const;

  // -- Setup

  Q_SLOT
  void
  reload_mixer ();

  void
  reload_current_mixer_device ();

  void
  update_balloon_setup ();

  void
  update_input_setup ();

  void
  update_icon_setup ();

  // -- Public signals

  Q_SIGNAL
  void
  sig_toggle_mixer ();

  Q_SIGNAL
  void
  sig_quit ();

  protected:
  // -- Protected methods

  bool
  event ( QEvent * event_n ) override;

  Q_SLOT
  void
  mixer_values_changed ();

  Q_SLOT
  void
  mixer_toggle_switch ();

  Q_SLOT
  void
  mouse_wheel_delta ( int wheel_delta_n );

  private:
  // -- Utility

  QString
  acquire_mixer_device () const;

  /// @brief Checks if the card is the opened device
  bool
  check_card_match ( const QSnd::Card_Info & info_n ) const;

  Q_SLOT
  void
  check_card_new ( std::shared_ptr< const QSnd::Card_Info > handle_n );

  Q_SLOT
  void
  check_card_removed ( std::shared_ptr< const QSnd::Card_Info > handle_n );

  void
  update_volume_values ( bool notify_n = false );

  // -- Mixer loading

  void
  load_mixer ();

  void
  close_mixer ();

  private:
  // -- Attributes
  const Tray::Setup * _setup = nullptr;
  const MWdg::Mixer_Device_Setup * _mixer_device_setup = nullptr;

  // Mixer
  QSnd::Mixer::Mixer * _snd_mixer = nullptr;
  QSnd::Mixer::Elem * _mx_elem = nullptr;

  // State flags
  bool _updating_scheduled = false;

  Shared _shared;
  std::unique_ptr< Icon > _tray_icon;
  std::unique_ptr< Notifier > _notifier;
};

} // namespace Tray
