/*
 * Espressif Modified MIT License
 *
 * Copyright (c) 2025 Espressif Systems (Shanghai) Co., LTD
 *
 * Permission is hereby granted for use **exclusively** with Espressif Systems products.
 * This includes the right to use, copy, modify, merge, publish, distribute, and sublicense
 * the Software, subject to the following conditions:
 *
 * 1. This Software **must be used in conjunction with Espressif Systems products**.
 * 2. The above copyright notice and this permission notice shall be included in all copies
 *    or substantial portions of the Software.
 * 3. Redistribution of the Software in source or binary form **for use with non-Espressif products**
 *    is strictly prohibited.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
 * FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 * SPDX-License-Identifier: MIT-ESPRESSIF
 */

#pragma once

#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include "audio_pipeline.h"

#if __has_include("audio_tone_uri.h")
    #include "audio_tone_uri.h"
#else
    #error "please refer the README, and then make the tone file"
#endif

typedef void (*tone_play_callback_t)(audio_element_status_t evt);

/**
 * @brief Enumeration of player pipeline states
 */
typedef enum {
    PIPE_STATE_IDLE,     /**< The pipeline is idle and not processing any audio */
    PIPE_STATE_RUNNING,  /**< The pipeline is actively processing and playing audio */
} pipe_player_state_e;

/**
 * @brief  Handle type for the audio player.
 */
typedef struct audio_player_s *audio_player_handle_t;

/**
 * @brief  Handle type for the audio recorder.
 */
typedef struct audio_recorder_s *audio_recorder_handle_t;

/**
 * @brief  Open the recorder pipeline and initialize necessary resources.
 *
 * @return  audio_recorder_handle_t Recorder handle, or NULL on failure.
 */
audio_recorder_handle_t recorder_pipeline_open();

/**
 * @brief  Start the recorder pipeline and begin capturing audio data.
 *
 * @param[in]  recorder  Recorder handle.
 *
 * * @return
 *       - ESP_OK               On success
 *       - ESP_ERR_INVALID_ARG  NULL pointer or invalid configuration
 */
esp_err_t recorder_pipeline_run(audio_recorder_handle_t recorder);

/**
 * @brief  Read audio data from the recorder pipeline.
 *
 * @param[in]  recorder  Recorder handle.
 * @param[in]  buffer    Pointer to the buffer where audio data will be stored.
 * @param[in]  len       Maximum number of bytes to read.
 *
 * @return
 *       - ESP_OK               On success
 *       - ESP_ERR_INVALID_ARG  NULL pointer or invalid configuration
 */
esp_err_t recorder_pipeline_read(audio_recorder_handle_t recorder, char *buffer, int len);

/**
 * @brief  Stop the recorder pipeline.
 *
 * @param[in]  recorder  Recorder handle.
 *
 * @return
 *       - ESP_OK               On success
 *       - ESP_ERR_INVALID_ARG  NULL pointer or invalid configuration
 */
esp_err_t recorder_pipeline_stop(audio_recorder_handle_t recorder);

/**
 * @brief  Close the recorder pipeline and release all resources.
 *
 * @param[in]  recorder  Recorder handle.
 *
 * @return
 *       - ESP_OK               On success
 *       - ESP_ERR_INVALID_ARG  NULL pointer or invalid configuration
 */
esp_err_t recorder_pipeline_close(audio_recorder_handle_t recorder);

/**
 * @brief  Open the player pipeline and initialize necessary resources.
 *
 * @return  audio_player_handle_t Player handle, or NULL on failure.
 */
audio_player_handle_t player_pipeline_open();

/**
 * @brief  Start the player pipeline and begin playback.
 *
 * @param[in]  player  Player handle.
 *
 * @return
 *       - ESP_OK               On success
 *       - ESP_ERR_INVALID_ARG  NULL pointer or invalid configuration
 */
esp_err_t player_pipeline_run(void);

/**
 * @brief  Stop the player pipeline.
 *
 * @param[in]  player  Player handle.
 *
 * @return
 *       - ESP_OK               On success
 *       - ESP_ERR_INVALID_ARG  NULL pointer or invalid configuration
 */
esp_err_t player_pipeline_stop(void);

/**
 * @brief  Write audio data to the player pipeline for playback.
 *
 * @param[in]  player  Player handle.
 * @param[in]  buffer  Pointer to the buffer containing audio data.
 * @param[in]  len     Number of bytes to write.
 *
 * @return
 *       - ESP_OK               On success
 *       - ESP_ERR_INVALID_ARG  NULL pointer or invalid configuration
 */
esp_err_t player_pipeline_write(audio_player_handle_t player, char *buffer, int len);

/**
 * @brief  Close the player pipeline and release all resources.
 *
 * @param[in]  player  Player handle.
 * 
 * @return
 *       - ESP_OK               On success
 *       - ESP_ERR_INVALID_ARG  NULL pointer or invalid configuration
 */
esp_err_t player_pipeline_close(audio_player_handle_t player);

/**
 * @brief  Initialize the tone playback system.
 *
 * @param[in]  callback  Callback function to be called when tone playback is triggered
 *
 * @return
 *       - ESP_OK               On success
 *       - ESP_ERR_INVALID_ARG  Invalid callback or other configuration error
 */
esp_err_t audio_tone_init(tone_play_callback_t callback);

/**
 * @brief  Stop the currently playing tone, if any.
 *
 * @return
 *       - ESP_OK  On success or if no tone is playing
 *       - ESP_FAIL  If stopping tone fails
 */
esp_err_t audio_tone_stop(void);

/**
 * @brief  Play a tone from the specified URL
 *
 * @param[in]  tone_url  The tone resource to be played, check 'audio_tone_uri.h'
 *
 * @return
 *       - ESP_OK               On success
 *       - ESP_ERR_INVALID_ARG  Invalid tone type or URL
 *       - ESP_FAIL             Other playback errors
 */
esp_err_t audio_tone_play(tone_type_t tone_url);


