#pragma once

#ifdef _MSC_VER

    #include <optional>
    #include <string>
    #include <utility>
    #include <vector>

    #include <physicalmonitorenumerationapi.h>
    #include <windows.h>

namespace detail {

extern BOOL enumMonitorsCallback(HMONITOR, HDC, LPRECT, LPARAM);

} // namespace detail

class Monitor {
  public:
    Monitor() = delete;
    Monitor(const Monitor&) = delete;
    Monitor(Monitor&& other) noexcept;
    ~Monitor();

    bool setBrightness(float percentage);
    float getBrightness();

    operator bool() const;

  private:
    struct PhysicalMonitor {
        PhysicalMonitor(HANDLE handle, const WCHAR* name) : handle(handle), name(name) {}

        HANDLE handle;
        std::wstring name;
    };

    friend BOOL detail::enumMonitorsCallback(HMONITOR, HDC, LPRECT, LPARAM);

    HMONITOR m_hMonitor;
    PhysicalMonitor m_physicalMonitor;

    std::optional<std::pair<DWORD, DWORD>> m_brightnessRange;
    bool m_errorOccurred = false;

    Monitor(HMONITOR hMonitor, PHYSICAL_MONITOR physicalMonitor);

    bool hasBrightnessCapability() const;
};

#endif

#if defined(__clang__) || defined(__GNUC__)

class Monitor {
  public:
    Monitor();

    bool setBrightness(float);
    float getBrightness();

    operator bool() const;

  private:
};

#endif
