/// 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 Mixer_Dev_Setup;
class Notifier;
class View_Setup;
} // namespace Tray
namespace QSnd
{
class Card_Info;
class Cards_Db;
} // namespace QSnd
namespace QSnd::Mixer
{
class Elem;
class Mixer;
} // namespace QSnd::Mixer

namespace Tray
{

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

  public:
  // -- Construction

  Mixer ( QSnd::Cards_Db * cards_db_n, QObject * parent_n = nullptr );

  ~Mixer () override;

  // -- Setup

  void
  set_mixer_dev_setup ( Mixer_Dev_Setup * setup_n );

  void
  set_view_setup ( View_Setup * setup_n );

  bool
  is_visible () const;

  // -- 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 ();

  Q_SLOT
  void
  reload_mixer ();

  // -- Notifier

  void
  setup_notifier ();

  void
  clear_notifier ();

  private:
  // -- Attributes
  Mixer_Dev_Setup * _mixer_dev_setup = nullptr;
  Tray::View_Setup * _view_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
