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

#pragma once

#include "mwdg/mixer/setup.hpp"
#include "mwdg/mixer/sliders/proxies_model.hpp"
#include "mwdg/mixer/switches/proxies_model.hpp"
#include "views/view_base.hpp"
#include <QPointer>
#include <QSplitter>
#include <memory>

// Forward declaration
namespace MState::Mixer
{
class States_Db;
}
namespace MState::Mixer
{
class State;
}
namespace MWdg::Mixer::Sliders
{
class Mixer;
class Status_Widget;
} // namespace MWdg::Mixer::Sliders
namespace MWdg::Mixer::Switches
{
class Mixer;
}
namespace Views
{
class Mixer_Setup;
}
namespace Wdg
{
class Style_Db;
}
namespace dpe
{
class Image_Allocator;
}
namespace QSnd
{
class Mixer_Simple;
}

namespace Views
{

/// @brief Mixer
///
class Mixer : public Views::View_Base
{
  Q_OBJECT

  public:
  // -- Construction

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

  ~Mixer () override;

  // -- Mixer device and view setup

  void
  set_mixer_dev_setup ( const MWdg::Mixer_Device_Setup * setup_n ) override;

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

  void
  set_view_setup ( Views::View_Base_Setup * setup_n ) override;

  void
  save_state ();

  // -- Proxies models

  MWdg::Mixer::Sliders::Proxies_Model *
  sliders_model ()
  {
    return &_sliders_model;
  }

  MWdg::Mixer::Switches::Proxies_Model *
  switches_model ()
  {
    return &_switches_model;
  }

  /// @brief Call to update the view when the proxies sorting has changed
  Q_SLOT
  void
  reload_proxies_models_sorted ();

  /// @brief Call to update the view when the proxies filters have changed
  Q_SLOT
  void
  reload_proxies_models_filtered ();

  // -- Streams available

  /// @brief Playback / capture selection is available
  bool
  streams_available () const
  {
    return _streams_available;
  }

  Q_SIGNAL
  void
  sig_streams_available ( bool value_n );

  // -- Playback

  Q_SLOT
  void
  show_playback ( bool flag_n );

  Q_SLOT
  void
  toggle_show_playback ();

  Q_SIGNAL
  void
  sig_show_playback_changed ( bool value_n );

  // -- Capture

  Q_SLOT
  void
  show_capture ( bool flag_n );

  Q_SLOT
  void
  toggle_show_capture ();

  Q_SIGNAL
  void
  sig_show_capture_changed ( bool value_n );

  // -- Slider value widget

  Q_SLOT
  void
  show_slider_value_widget ();

  protected:
  // -- Protected slots

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

  protected:
  // -- Protected methods

  void
  keyPressEvent ( QKeyEvent * event_n ) override;

  void
  showEvent ( QShowEvent * event_n ) override;

  void
  hideEvent ( QHideEvent * event_n ) override;

  private:
  // -- Utility

  void
  set_streams_available ( bool flag_n );

  void
  update_stream_availability ();

  void
  clear_view ();

  void
  setup_view ();

  private:
  // -- Attributes
  MState::Mixer::States_Db * _mixer_states_db = nullptr;

  /// @brief Mixer object
  std::unique_ptr< QSnd::Mixer::Mixer > _qsnd_mixer;
  std::shared_ptr< MState::Mixer::State > _mixer_state;

  Views::Mixer_Setup * _view_setup = nullptr;
  MWdg::Mixer::Setup _mixer_setup;

  // Models
  MWdg::Mixer::Sliders::Proxies_Model _sliders_model;
  MWdg::Mixer::Switches::Proxies_Model _switches_model;
  bool _streams_available = false;

  // widgets
  std::unique_ptr< QSplitter > _splitter;
  std::unique_ptr< MWdg::Mixer::Sliders::Mixer > _mixer_sliders;
  std::unique_ptr< MWdg::Mixer::Switches::Mixer > _mixer_switches;
  struct
  {
    bool sliders = false;
    bool switches = false;
    bool splitter = false;
  } _visibility;
  struct
  {
    QMargins sliders;
    QMargins switches;
  } _splitter_margins;

  QPointer< MWdg::Mixer::Sliders::Status_Widget > _status_wdg;
  unsigned int _status_group_idx = ~0;
  unsigned int _status_column_idx = ~0;
};

} // namespace Views
