#include "GdiCapturer.h"
#include <cassert>

namespace avrecorder {
namespace video {

bool GdiCapturer::open(const CaptureTarget& target, int width, int height) {
#ifdef PLATFORM_WINDOWS
    close();
    if (target.type != CaptureTargetType::Window) return false;
    m_hwnd = target.hwnd;
    m_width = width;
    m_height = height;
    _srcHdc = GetWindowDC(m_hwnd);
    _dstHdc = CreateCompatibleDC(_srcHdc);
    _bitmap = CreateCompatibleBitmap(_srcHdc, width, height);
    SelectObject(_dstHdc, _bitmap);

    _bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    _bitmapInfo.bmiHeader.biPlanes = 1;
    _bitmapInfo.bmiHeader.biBitCount = 24;
    _bitmapInfo.bmiHeader.biWidth = width;
    _bitmapInfo.bmiHeader.biHeight = height;
    _bitmapInfo.bmiHeader.biCompression = BI_RGB;
    _bitmapInfo.bmiHeader.biSizeImage = width * height;

    _frame = Frame<MediaType::VIDEO>::Alloc(AV_PIX_FMT_BGR24, width, height);
    return true;
#else
    return false;
#endif
}

void GdiCapturer::close() {
#ifdef PLATFORM_WINDOWS
    if (_frame) { av_frame_free(&_frame); _frame = nullptr; }
    if (_dstHdc) { DeleteObject(_dstHdc); _dstHdc = nullptr; }
    if (_bitmap) { DeleteObject(_bitmap); _bitmap = nullptr; }
    // _srcHdc 由系统管理，无需手动释放
#endif
}

AVFrame* GdiCapturer::getFrame() {
#ifdef PLATFORM_WINDOWS
    if (!_srcHdc || !_dstHdc || !_frame) return nullptr;
    BitBlt(_dstHdc, 0, 0, m_width, m_height, _srcHdc, 0, 0, SRCCOPY);
    auto linesize = _frame->linesize[0];
    for (int row = 0; row < m_height; ++row) {
        GetDIBits(_dstHdc, _bitmap, m_height - 1 - row, 1, _frame->data[0] + row * linesize, &_bitmapInfo, DIB_RGB_COLORS);
    }
    if (m_drawCursor) {
        drawCursor(_dstHdc);
    }
    return _frame;
#else
    return nullptr;
#endif
}

void GdiCapturer::drawCursor(HDC hdc)
{
    CURSORINFO ci = {sizeof(CURSORINFO)};
    if (!GetCursorInfo(&ci))
        return;
    if (ci.flags != CURSOR_SHOWING)
        return;

    RECT rect;
    GetWindowRect(m_hwnd, &rect);
    POINT pos = {ci.ptScreenPos.x - rect.left, ci.ptScreenPos.y - rect.top};

    DrawIconEx(hdc, pos.x, pos.y, ci.hCursor, 0, 0, 0, NULL, DI_NORMAL | DI_COMPAT);
}
} // namespace video
} // namespace avrecorder
