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

#pragma once

#include "cmd_options.hpp"
#include "desktop_items_setup.hpp"
#include "mstate/mixer/states_db.hpp"
#include "qsnd/cards_db.hpp"
#include <QDialog>
#include <QObject>
#include <QPointer>
#include <memory>

// Forward declaration
class Main_Window;
class Dialog_Settings;
namespace Tray
{
class Mixer;
}

/// @brief Manages all items that appear on the desktop
///
/// The managed window items are
///  - Main_Mixer
///  - Tray::Mixer ( with tray icon )
///
/// All settings are always present in the setup tree.
/// The setup tree gets initialized in the constructor
/// and on calling init_settings().
/// On destruction it gets written to the storage (disk).
class Desktop_Items : public QObject
{
  Q_OBJECT

  public:
  // -- Construction

  Desktop_Items ( QObject * parent_n = nullptr );

  ~Desktop_Items () override;

  /// @brief Options that came from the command line or a second instance
  ///
  const CMD_Options &
  cmd_opts () const
  {
    return _cmd_opts;
  }

  /// @brief Reads options from storage and command line
  ///
  /// @return A negative value on an error
  int
  init_settings ( int argc, char * argv[] );

  /// @brief Message to be sent to an other instance
  ///
  /// @return The message
  QString
  message_to_other_instance () const;

  /// @brief Start the mixer window and/or tray icon
  ///
  void
  start ( bool restore_session_n = false );

  // -- Event handling

  bool
  event ( QEvent * event_n ) override;

  bool
  eventFilter ( QObject * obj_n, QEvent * event_n ) override;

  // -- Signals

  Q_SIGNAL
  void
  sig_quit ();

  // -- Public slots

  /// @brief Reads messages from other instances
  Q_SLOT
  void
  parse_message ( QString msg_n );

  // Main mixer minimize / raise

  Q_SLOT
  void
  main_mixer_raise ();

  Q_SLOT
  void
  main_mixer_close ();

  Q_SLOT
  void
  main_mixer_toggle_by_tray ();

  // Dialogs

  Q_SLOT
  void
  show_dialog_settings ();

  Q_SLOT
  void
  show_dialog_about ();

  Q_SLOT
  void
  show_dialog_about_qt ();

  /// @brief Closes and destroy all widgets
  Q_SLOT
  void
  shutdown ();

  /// @brief Shuts down and emits sig_quit()
  Q_SLOT
  void
  quit ();

  protected:
  // -- Protected slots

  Q_SLOT
  void
  main_mixer_reload_view ();

  /// @brief Lets widgets reload the inputs setup from the setup tree
  ///
  Q_SLOT
  void
  reload_inputs_setup ();

  /// @return true if the tray icon is visible
  ///
  Q_SLOT
  void
  tray_mixer_update_visibility ();

  Q_SLOT
  void
  tray_mixer_reload_mdev ();

  Q_SLOT
  void
  tray_mixer_reload_current_mdev ();

  Q_SLOT
  void
  tray_mixer_update_balloon_setup ();

  private:
  // -- Private methods

  /// @brief Creates a new main mixer window
  ///
  void
  main_mixer_create ();

  /// @brief Destroys the main mixer window
  ///
  void
  main_mixer_destroy ();

  /// @brief True if the main mixer exists and is visible
  ///
  bool
  main_mixer_visible ();

  /// @brief Will be called shortly after the mixer window was closed
  ///
  void
  main_mixer_closed ();

  /// @brief Creates a tray mixer instance
  ///
  void
  tray_mixer_create ();

  void
  tray_mixer_destroy ();

  bool
  tray_mixer_visible ();

  /// @brief Command line option parser
  ///
  /// @return A negative value on an error
  int
  parse_cmd_options ( int argc, char * argv[] );

  private:
  // -- Attributes
  int _evt_mixer_closed = 0;
  Desktop_Items_Setup _dsetup;
  QSnd::Cards_Db _cards_db;
  MState::Mixer::States_Db _mixer_states_db;

  std::unique_ptr< Tray::Mixer > _tray_mixer;
  std::unique_ptr< Main_Window > _main_mixer;

  // Dialogs
  QPointer< QDialog > _dialog_settings;
  QPointer< QDialog > _dialog_about;

  CMD_Options _cmd_opts;
  bool _started = false;
  bool _shutdown = false;
};
