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

#pragma once

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

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

/// @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().
class Desktop_Items : public QObject
{
  Q_OBJECT

  public:
  // -- Construction

  Desktop_Items ( QObject * parent_n = nullptr );

  ~Desktop_Items () override;

  // -- Command line options

  /// @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[] );

  // -- DBus

  void
  dbus_connect ();

  bool
  dbus_connected () const
  {
    return _dbus_connected;
  }

  bool
  dbus_notify_remote ();

  // -- Application start

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

  // -- Public slots

  Q_SLOT
  void
  select_ctl ( const QString & ctl_str_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 ();

  // -- Shutdown

  Q_SLOT
  void
  commit_data ( QSessionManager & manager_n );

  Q_SLOT
  void
  save_state ( QSessionManager & manager_n );

  Q_SLOT
  void
  save_settings ();

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

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

  Q_SIGNAL
  void
  sig_quit ();

  private:
  // -- Event processing

  bool
  event ( QEvent * event_n ) override;

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

  // -- Slot interface

  Q_SLOT
  void
  main_mixer_reload_view ();

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

  Q_SLOT
  void
  tray_mixer_update_visibility ();

  Q_SLOT
  void
  tray_mixer_update_icon ();

  Q_SLOT
  void
  tray_mixer_reload_mixer_dev ();

  Q_SLOT
  void
  tray_mixer_reload_current_mixer_dev ();

  Q_SLOT
  void
  tray_mixer_update_balloon_setup ();

  Q_SLOT
  void
  tray_mixer_update_input_setup ();

  // -- Utility

  /// @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< Views::Settings_Dialog > _dialog_settings;
  QPointer< QDialog > _dialog_about;

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

  // DBus
  QString _dbus_object_path;
  QString _dbus_service_name;
  bool _dbus_connected = false;
  Desktop_Items_DBus_Adaptor _dbus_adaptor;
};
