#include "ClipboardOperations.hpp"

HGLOBAL ClipboardOperations::AllocateMemory(size_t size)
{
    return GlobalAlloc(GMEM_MOVEABLE, size);
}

void ClipboardOperations::FreeMemory(HGLOBAL hMem)
{
    if (hMem)
        GlobalFree(hMem);
}

void* ClipboardOperations::LockMemory(HGLOBAL hMem)
{
    if (!hMem)
        return nullptr;

    return GlobalLock(hMem);
}

bool ClipboardOperations::UnlockMemory(HGLOBAL hMem)
{
    if (!hMem)
        return false;

    return GlobalUnlock(hMem) || GetLastError() == NO_ERROR;
}

size_t ClipboardOperations::GetMemorySize(HGLOBAL hMem)
{
    if (!hMem)
        return 0;

    return GlobalSize(hMem);
}

bool ClipboardOperations::IsMemoryValid(HGLOBAL hMem)
{
    return hMem != nullptr && GetMemorySize(hMem) > 0;
}

bool ClipboardOperations::CopyToMemory(HGLOBAL hMem, const void* data, size_t size)
{
    if (!hMem || !data || size == 0)
        return false;

    void* pLocked = LockMemory(hMem);
    if (!pLocked)
        return false;

    memcpy(pLocked, data, size);
    UnlockMemory(hMem);

    return true;
}

bool ClipboardOperations::CopyFromMemory(void* dest, HGLOBAL hMem, size_t size)
{
    if (!dest || !hMem || size == 0)
        return false;

    void* pLocked = LockMemory(hMem);
    if (!pLocked)
        return false;

    memcpy(dest, pLocked, size);
    UnlockMemory(hMem);

    return true;
}

HGLOBAL ClipboardOperations::CreateTextData(const std::wstring& text)
{
    size_t size = CalculateTextSize(text);
    HGLOBAL hMem = AllocateMemory(size);

    if (!hMem)
        return nullptr;

    if (!CopyToMemory(hMem, text.c_str(), size))
    {
        FreeMemory(hMem);
        return nullptr;
    }

    return hMem;
}

std::wstring ClipboardOperations::ExtractTextData(HGLOBAL hData)
{
    if (!hData)
        return {};

    wchar_t* pText = static_cast<wchar_t*>(LockMemory(hData));
    if (!pText)
        return {};

    std::wstring result = pText;
    UnlockMemory(hData);

    return result;
}

size_t ClipboardOperations::CalculateTextSize(const std::wstring& text)
{
    return (text.size() + 1) * sizeof(wchar_t);
}