#ifndef __BASIC_FUCN_H__
#define __BASIC_FUCN_H__
#define __STDC_FORMAT_MACROS

#include <functional>
#include <mutex>
#include <thread>
#include <cstdio>

extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/error.h>
}

#include <winerror.h>
// ***************
// MUTEX
extern std::mutex __mtx;

// ***************
// debug function

#define __AVDEBUG

#ifdef __AVDEBUG
#define __DebugPrint(fmtStr, ...) \
    std::printf("[" __FILE__ ", line:%d, func:%s] " fmtStr "\n", __LINE__, __FUNCTION__, ##__VA_ARGS__)
#else
#define __DebugPrint(fmtStr, ...)
#endif

#define __Str(exp) #exp

// Legacy __Check* macros removed. Use CheckBool/CheckHR/CheckFF helpers below.

// ================= Function-based checks (preferred going forward) =================
// Return false on failure and print diagnostics. Callers can early-return appropriate values.
inline bool CheckBool(bool condition, const char* what = nullptr)
{
    if (!condition) {
        if (what) {
            __DebugPrint("Check failed: %s", what);
        } else {
            __DebugPrint("Check failed");
        }
        return false;
    }
    return true;
}

inline bool CheckHR(HRESULT hr, const char* what = nullptr)
{
    if (FAILED(hr)) {
        if (what) {
            __DebugPrint("HRESULT failed (0x%08lx): %s", static_cast<unsigned long>(hr), what);
        } else {
            __DebugPrint("HRESULT failed (0x%08lx)", static_cast<unsigned long>(hr));
        }
        return false;
    }
    return true;
}

inline bool CheckFF(int rc, const char* what = nullptr)
{
    if (rc < 0) {
        char __errbuf[AV_ERROR_MAX_STRING_SIZE];
        av_strerror(rc, __errbuf, sizeof(__errbuf));
        if (what) {
            __DebugPrint("FFmpeg failed: rc=%d (%s) at %s", rc, __errbuf, what);
        } else {
            __DebugPrint("FFmpeg failed: rc=%d (%s)", rc, __errbuf);
        }
        return false;
    }
    return true;
}

enum class MediaType {
    AUDIO,
    VIDEO
};

// ***************
// memory function

template <typename T, typename Func>
void Free(T*& ptr, Func&& func)
{
    static_assert(std::is_convertible_v<Func, std::function<void()>>, "Type Func should be std::function<void()>");
    if (ptr == nullptr) {
        return;
    }
    func();
    ptr = nullptr;
}

//***************
// time function

// Sleep x ms
inline void SleepMs(int timeMs)
{
    std::this_thread::sleep_for(std::chrono::milliseconds(timeMs));
}

// =================== 音频全局设置 ===================
// 此处配置影响全局的音频捕获和编码参数，旨在平衡音质与文件大小。

// --- 采样率 (Sample Rate) ---
// 48000 Hz: 专业音频和视频的标准，提供高质量的音频。
// 44100 Hz: CD音质标准，兼容性好。
// 16000 Hz: 通讯领域常用，适用于纯语音，体积小。
// 推荐使用 48000 或 44100。
constexpr int AUDIO_SAMPLE_RATE = 48000;

// --- 声道数 (Channels) ---
// 1 (Mono): 单声道。体积小，适用于语音、旁白等场景。兼容性最佳。
// 2 (Stereo): 立体声。提供空间感，适用于音乐、游戏等场景。体积是单声道的两倍。
// 为了平衡音质和文件大小，推荐使用单声道。
constexpr int AUDIO_CHANNEL = 1;

// --- 采样格式 (Sample Format) ---
// FFmpeg编码器期望的输入格式。捕获的PCM数据会被重采样成此格式。
// AV_SAMPLE_FMT_FLTP: 浮点型，平面存储。可以提供更大的动态范围。
constexpr AVSampleFormat AUDIO_FMT = AV_SAMPLE_FMT_FLTP;

// --- 捕获采样位深 (Capture Bit Depth) ---
// 从系统音频设备请求的原始PCM数据的位深度。
// 16-bit (Signed Integer): 兼容性极好，是大多数音频设备和API的标准格式。
// 编码时，此格式数据会被转换为上面定义的 AUDIO_FMT (如32-bit float)。
constexpr int AUDIO_CAPTURE_BITS_PER_SAMPLE = 16;

// --- 设备索引 ---
constexpr int MICROPHONE_INDEX = 0;
constexpr int SPEAKER_INDEX = 1;

#endif
