/* Copyright (c) 2020-2023 The Creators of Simphone

   See the file COPYING.LESSER.txt for copying permission.
*/

#ifndef SETTINGS_H
#define SETTINGS_H

#include "simcore.h"

#include <QCheckBox>
#include <QRadioButton>
#include <QSpinBox>
#include <QComboBox>
#include <QFile>
#include <QSet>

namespace Ui {
class Settings;
}

class CheckBoxSetting : public QCheckBox
{
  Q_OBJECT

  typedef QCheckBox Parent;

public:
  explicit CheckBoxSetting(QWidget * parent = 0);

  void prepare(simnumber value) { m_dirty = false, m_value = int(value); }
  bool isDirty() const { return m_dirty; }

  int getValue() const { return m_value; }
  int getValue(int dirty) const { return m_dirty ? dirty : m_value; }

  int getCheckedState(int unchecked, int partial, int checked) const;
  void setCheckedState(int unchecked, int checked);

  void set(simnumber value, int unchecked, const char * param = 0);

protected:
  void nextCheckState() Q_DECL_OVERRIDE { Parent::nextCheckState(), m_dirty = true; }

private:
  bool m_dirty;
  int m_value;
};

class SpinBoxSetting : public QSpinBox
{
  Q_OBJECT

  typedef QSpinBox Parent;

public:
  explicit SpinBoxSetting(QWidget * parent = 0);

  void prepare(QCheckBox * checkBox, const char * param, simnumber value, int scaleFactor = 1);

  int getValue() const;

private:
  int m_value;
  int m_defaultValue;
  int m_scaleFactor;
  QCheckBox * m_checkbox;
};

class RadioButtonSetting : public QRadioButton
{
  Q_OBJECT

  typedef QRadioButton Parent;

public:
  explicit RadioButtonSetting(QWidget * parent = 0);

  void prepare(simnumber value, int scaleFactor = 0);

  int getScaledValue(int value) const;
  int getValue();

protected:
  void nextCheckState() Q_DECL_OVERRIDE { Parent::nextCheckState(), m_dirty = true; }

private:
  bool m_dirty;
  int m_value;
  int m_scaleFactor;
};

class ComboBoxSetting : public QComboBox
{
  Q_OBJECT

  typedef QComboBox Parent;

public:
  explicit ComboBoxSetting(QWidget * parent = 0);
};

class Settings : public QDialog
{
  Q_OBJECT

  typedef QDialog Parent;

public:
  explicit Settings(QWidget * parent, char code);
  ~Settings() Q_DECL_OVERRIDE;

  static Settings * isActive() { return mc_active; }

  void prepareAudio(bool valid);
  void prepare();
  void prepareCiphers(QSet<QString> * ciphers, const simtype array);

  static QString getFileName(const QString & fileName);
  static QString getConfigDir(bool init);
  static int writeString(QFile * file, const QString & text);

  static int setAutostart(int autostart, bool init);
  static void setAutostartArguments(const QStringList & args) { mc_autostartArguments = args; }

  static void setInvalidDevices(bool output, bool input, bool ring);
  static void getInvalidDevices(bool * output, bool * input, bool * ring);

  bool setAudioDevices(char selected);

  void resetStatistics();
  static double addStatistics(QList<double> * statistics, double value);

private slots:
  void on_statisticsButton_clicked();
  void on_autoButton_clicked();
  void on_downloadButton_clicked();
  void on_playButton_clicked();
  void on_testButton_clicked();
  void on_enableButton_clicked();
  void on_ciphersButton_clicked();

  void on_buttonBox_accepted();
  void on_buttonBox_rejected();

  void on_outputList_activated(int ndx);
  void on_inputList_activated(int ndx);
  void on_ringList_activated(int ndx);

  void on_tabWidget_currentChanged(int index);

  void onSlowdownButtonClicked();
  void onSpeedupButtonClicked();

  void onStatisticsTimeout();

  void onSignalContactAudioChanged(unsigned id, SimAudioState newState);
  void onSignalInvalidAudioDevice(bool valid);
  void onSignalSpeech(unsigned id, int, int probability, int);

  void onSignalFontChanged() const;

private:
  bool eventFilter(QObject * obj, QEvent * event) Q_DECL_OVERRIDE;
  void changeEvent(QEvent * event) Q_DECL_OVERRIDE;

  void hideAudioSettings(bool show);
  void hideNonAudioTabs();
  void enableNonAudioTabs(bool enable);
  void enableAudioTab(bool enable);
  void enableAudioSettings(bool enable);

  Ui::Settings * ui;

  static int mc_current;
  static Settings * mc_active;
  static QStringList mc_autostartArguments;

  static int mc_statisticsInterval;
  static int mc_statisticsIncrement;
  static simunsigned mc_statisticsIncrementTime;
  static bool mc_statisticsDecrement;
  static QList<double> mc_statisticsDownload;
  static QList<double> mc_statisticsUpload;

  char m_code;
  char m_testing;
  bool m_password;

  static bool mc_invalidOutput;
  static bool mc_invalidInput;
  static bool mc_invalidRing;

  int m_invalid;
  int m_outputSelected;
  int m_inputSelected;
  int m_ringSelected;

  QString m_output;
  QString m_input;
  QString m_ring;
  int m_latency;
  int m_autoAnswer;

  QString m_os;
  int m_style;

  QSet<QString> m_preferredCiphers;

  QMessageBox * m_statisticsBox;
  QTimer m_statisticsTimer;

public:
  QList<CheckBoxSetting *> m_checkBoxes;
  QList<RadioButtonSetting *> m_radioButtons;
  QList<ComboBoxSetting *> m_comboBoxes;
};

#endif
