#pragma once

#include <cstdint>

#include "../Common/serial_port.hpp"

class DfPlayer {
public:
    explicit DfPlayer(UART_HandleTypeDef* uart) : serialPort(new SerialPort(uart, kLength, kTimeout)) {}

    ~DfPlayer() {
        delete serialPort;
    }

    void Play();
    void Stop();
    void SetVolume(uint8_t volume);
    void PlayTrack(uint16_t track);

private:
    enum class Command : uint8_t {
        kNext                    = 0x01,
        kPrevious                = 0x02,
        kPlayTrack               = 0x03,
        kVolumeUp                = 0x04,
        kVolumeDown              = 0x05,
        kSetVolume               = 0x06,
        kSetEQ                   = 0x07,
        kSingleLoopPlayTrack     = 0x08,
        kSetPlaybackDevice       = 0x09,
        kEnterSleep              = 0x0A,
        kResetModule             = 0x0C,
        kPlay                    = 0x0D,
        kPause                   = 0x0E,
        kPlayFolderTrack         = 0x0F,
        kSetAmplification        = 0x10,
        kLoopAll                 = 0x11,
        kPlayMp3FolderTrack      = 0x12,
        kInsertAd                = 0x13,
        kStopAdPlayBackground    = 0x15,
        kStop                    = 0x16,
        kQueryStatus             = 0x42,
        kQueryVolume             = 0x43,
        kQueryEQ                 = 0x44,
        kQueryUDiskTotalFiles    = 0x47,
        kQueryTFCardTotalFiles   = 0x48,
        kQueryFlashTotalFiles    = 0x49,
        kQueryUDiskCurrentTrack  = 0x4B,
        kQueryTFCardCurrentTrack = 0x4C,
        kQueryFlashCurrentTrack  = 0x4D,
    };

    static constexpr uint32_t kLength  = 128;
    static constexpr uint32_t kTimeout = 10;
    SerialPort* serialPort;

    void SendCommand(Command cmd, uint16_t param = 0);

    static constexpr uint8_t kStartByte = 0x7E;
    static constexpr uint8_t kVersion   = 0xFF;
    static constexpr uint8_t kFeedback  = 0x00;
    static constexpr uint8_t kEndByte   = 0xEF;
};
