/*Copyright (C) 2010-2023 Duncan Deveaux

This file is part of Hikou no mizu.

Hikou no mizu is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Hikou no mizu is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Hikou no mizu.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef DEF_PLAYLIST
#define DEF_PLAYLIST

#include <cstddef>
#include <vector>
#include <string>
#include <random>
#include <chrono>

class Music; ///< Referenced for the actual music playback

/// A song data (title, author & path to the music file)
struct SongData
{
    SongData() {}

    SongData(const std::string &songTitle, const std::string &songAuthor,
             const std::string &songPath) :
    title(songTitle), author(songAuthor), path(songPath) {}

    std::string title, author;
    std::string path; ///< Path to the file, key to differentiate the songs
};

/// A playing \p music associated with the song data of index \p ix
struct PlayingMusic
{
    PlayingMusic() : ix(0), music(nullptr) {}

    std::size_t ix;
    Music *music;
};

/// Stores a playlist data (list, volume) and plays corresponding musics
/// Designed to be used in PlaylistPlayer
class Playlist
{
    public:
        explicit Playlist(const std::vector<SongData> &songs);
        Playlist(const Playlist &copied) = delete;
        Playlist &operator=(const Playlist &copied) = delete;
        ~Playlist();

        void update();
        void setVolume(float volume);

        /// Switch to a random next song and play it
        bool playNext();
        void stopSong(); ///< Stop the currently playing song
        bool songEnded(); ///< Has the current song ended?

        /// Returns the data from the current song
        const SongData &getData() const;

    private:
        /// Starts the music at index \p ix.
        /// Returns false if the music could not be opened
        bool startMusic(std::size_t ix);
        void destroy(); ///< Destroy m_playingMusic if needed

        std::mt19937 m_generator;

        PlayingMusic m_playing; ///< The currently playing music
        std::chrono::duration<double> m_endTime;

        std::vector<SongData> m_playlist; ///< List of the paths to the songs
        float m_volume;
};

#endif
