/*
*  qm_mpdcom.h
*  QUIMUP MPD command class
*  © 2008-2024 Johan Spee
*  SPDX-License-Identifier: GPL-3.0-or-later
*/

#ifndef QM_MPDCOM_H
#define QM_MPDCOM_H

#if (defined(LIBMPDCLIENT_MAJOR_VERSION) && LIBMPDCLIENT_MAJOR_VERSION > 1) && (defined(LIBMPDCLIENT_MINOR_VERSION) && LIBMPDCLIENT_MINOR_VERSION > 11)
#define libmpd_filelist 1
#else
#define libmpd_filelist 0
#endif


#include <unistd.h> 		// for usleep
#include <mpd/client.h>
#include <stdlib.h>
#include <sys/socket.h>     // for status_check
#include <sys/poll.h>       // for status_check
#include <QObject>
#include <QTimer>
#include <QList>
#include <QListIterator>
#include <QTextStream>
#include <QFile>
#include <QDir>
#include <QDateTime>
#include <QMessageBox>
#include <QProcess>
#include <QThread>

#include "qm_config.h"
#include "qm_songinfo.h"
#include "qm_itemlist.h"
#include "qm_commandlist.h"
#include "qm_task.h"

typedef struct qm_output
{
    uint id;
    bool enabled;
    QString name;
}
qm_output;

typedef QList<qm_output> qm_outputList;
typedef QList<int> qm_IDlist;

/*
    string != NULL_STRING) must allow "" (i.e. isEmpty),
    but it cannot be QString() (i.e. isNull) because QString()
    compares equal to QString(""), which is what we do NOT want.
    So we use a string that we are very unlikely to encounter:
*/
#define NULL_STRING "['/_^!~]"

class qm_mpdCommand : public QObject
{
    Q_OBJECT

public:
    qm_mpdCommand(qm_Config *);
    virtual ~qm_mpdCommand ();

private slots:
    void on_workdone_sgnl(uchar);
    void on_threadfinished_sgnl();
    bool status_check();

public slots:
    void mpd_try_connect(bool);
    void stop_connect_thread();
    void mpd_disconnect(bool sendsignal = true);
    void prev();
    void stop();
    void play(bool reload = false);
    void pause();
    void resume();
    void next();
    void play_this(uint);
    void set_random(bool);
    void set_repeat(bool);
    void set_single(bool);
    void set_consume(bool);
    void set_volume(int);
    void volume_up(int);
    void volume_down(int);
    void set_seek(uint);
    void update_all();
    bool get_album_art(QImage*);
    void reset_playlist();
    QString get_version(bool);
    qm_outputList get_outputs();
    bool set_outputs(qm_outputList);
    void set_xfade(uint);
    void set_timeout(uint);
    void set_replaygain_mode(int);
    void configure_connection();
    int get_listchanger();
    int execute_commands(qm_commandList, bool);
    bool execute_single_command(qm_mpd_command, bool);
    void clear_list();
    void shuffle_list();
    void get_statistics();
    void reset_current_song();
    void show_messagebox(QString, QString);
    void set_songinfo(qm_songInfo*);
    void get_autodetect_params();
    QString save_playlist(QString);
    QString save_selection(QStringList, QString);
    QString get_year_for_album(QString, QString);
    qm_itemList get_albumlist(bool);
    qm_itemList get_album_searchlist(QString);
    qm_itemList get_albums_for_artist(QString);
    qm_itemList get_artistlist();
    qm_itemList get_artist_searchlist(QString);
    qm_itemList get_dirlist(QString);
    qm_itemList get_dir_searchlist(QString);
    qm_itemList get_songlist();
    qm_itemList get_song_searchlist(QString);
    qm_itemList get_songs_for_any(QString, QString, QString);
    qm_itemList get_genrelist();
    qm_itemList get_genre_searchlist(QString);
    qm_itemList get_artists_for_genre(QString);
    qm_itemList get_playlistlist();
    qm_itemList get_items_for_playlist(QString);
    qm_itemList get_yearlist();

signals:
    void signal_status_info(mpd_status *);
    void signal_new_song();
    void signal_connected(bool, bool);
    void signal_playlist_update(qm_songinfo, int);
    void signal_statistics(QString);
    void signal_update_ready();
    void signal_playlist_saved();

private:
    void mpd_re_connect();
    bool mpd_do_connect();
    void get_playlist();
    void get_info_for_song(qm_songInfo *, mpd_song *);
    QString get_mpdconf_path();
    QString get_etc_default_mpd();
    QString find_config_files(bool);
    QString get_musicPath();
    QString get_password();
    QString get_host();
    int get_port();
    QString get_string(QString);
    bool error_check(QString, uint song_id = 0);
    QString fix_track_number (QString);
    bool is_mpd_running(bool);
    bool is_mpd_installed(bool);
    bool start_mpd();
    void search_directory_tree(QString, QString);
    bool validate_ip_address(QString);
    //  variables
    mpd_connection *p_conn;
    QTimer *statusLoop;
    qm_songInfo *current_songinfo;
    qm_Config *config;
    qm_itemList dirsearchlist;
    QThread *connect_Thread;
    qm_workerTask *connect_Task;

    bool
        b_is_on_start,
        b_shutting_down,
        b_statcheck_busy,
        b_mpdconf_found,
        b_dbase_updating,
        b_try_connect_ok,
        b_new_conn_keep,
        b_reload,
        b_no_volume,
        b_remote_server;

    int
        current_playlist,
        current_song_pos,
        current_song_id,
        current_status,
        current_volume,
        mpd_socket_fds;

    uint
        plist_lenght,
        server_port;

    QString
        server_name,
        server_password,
        mpdconf_path;
};

#endif // QM_MPDCOM_H
