#include <BUZZER_Driver.h>

#define TASK_PRIORITY 20
#define TASK_STACK    2048
#define OCTAVE        6

namespace drivers
{

    Buzzer::Buzzer()
    {
        LOG_INFO("Initializing Beeper");
        pinMode(buzzerPin, OUTPUT);
        ledcAttach(buzzerPin, 1000, 8);
        m_bp.pin = buzzerPin;
        m_bp.beeperTask = NULL;
        beep(50, NOTE_G);
    }

    Buzzer::~Buzzer()
    {
        beepStop();
        ledcDetach(buzzerPin);
        pinMode(buzzerPin, INPUT);
    }

    void Buzzer::beep(const uint16_t tBeep, const note_t note)
    {
        beepStop();
        m_bp.tOn = tBeep;
        m_bp.tOff = 0;
        m_bp.note = note;
        xTaskCreate(beepTask, "beeper", TASK_STACK, static_cast<void *>(&m_bp), TASK_PRIORITY, &m_bp.beeperTask);
    }
    
    void Buzzer::beepRepeat(const uint16_t tOn, const uint16_t tOff, const note_t note)
    {
        beepStop();
        m_bp.tOn = tOn;
        m_bp.tOff = tOff;
        m_bp.note = note;
        xTaskCreate(beepTask, "beeper", TASK_STACK, static_cast<void *>(&m_bp), TASK_PRIORITY, &m_bp.beeperTask);     
    }

    void Buzzer::beepStop()
    {
        if (m_bp.beeperTask != NULL)
            vTaskDelete(m_bp.beeperTask);
        ledcWriteTone(m_bp.pin, 0); // off
        m_bp.beeperTask = NULL;
    }
    
    void Buzzer::beepTask(void *params)
    {
        LOG_DEBUG("Beeper Task Created");
        beep_params_t *bPar = static_cast<beep_params_t *>(params);
        while (true)
        {
            ledcWriteNote(bPar->pin, bPar->note, OCTAVE); // on with selected note
            vTaskDelay(pdMS_TO_TICKS(bPar->tOn));
            ledcWriteTone(bPar->pin, 0); // off
            if (bPar->tOff == 0)
                break;
            vTaskDelay(pdMS_TO_TICKS(bPar->tOff));
        }
        LOG_DEBUG("Beeper Task Ended");
        bPar->beeperTask = NULL;
        vTaskDelete(NULL);
    }
}
