from ctypes import Array, Structure, _Pointer, c_uint
from ctypes.wintypes import BOOL, DWORD, HMONITOR, INT, LARGE_INTEGER, LONG, PFLOAT, POINT, RECT, UINT, ULARGE_INTEGER, WCHAR
from typing_extensions import TypedDict

from d3dshot.dll import _HRESULT, _IUnknown, _ProcessFunc, _ProcessFuncRegionArg, _ProcessFuncReturn
from d3dshot.dll.d3d import ID3D11Device

class _DXGIOutputPosition(TypedDict):
    left: LONG
    top: LONG
    right: LONG
    bottom: LONG

class _DXGIOutput(TypedDict):
    name: str
    position: _DXGIOutputPosition
    resolution: tuple[tuple[LONG, LONG], tuple[LONG, LONG]]
    rotation: int
    is_attached_to_desktop: bool

class LUID(Structure):
    LowPart: DWORD
    HighPart: LONG

class DXGI_ADAPTER_DESC1(Structure):
    Description: Array[WCHAR]
    VendorId: UINT
    DeviceId: UINT
    SubSysId: UINT
    Revision: UINT
    DedicatedVideoMemory: ULARGE_INTEGER
    DedicatedSystemMemory: ULARGE_INTEGER
    SharedSystemMemory: ULARGE_INTEGER
    AdapterLuid: LUID
    Flags: UINT

class DXGI_OUTPUT_DESC(Structure):
    DeviceName: Array[WCHAR]
    DesktopCoordinates: RECT
    AttachedToDesktop: BOOL
    Rotation: UINT
    Monitor: HMONITOR

class DXGI_OUTDUPL_POINTER_POSITION(Structure):
    Position: POINT
    Visible: BOOL

class DXGI_OUTDUPL_FRAME_INFO(Structure):
    LastPresentTime: LARGE_INTEGER
    LastMouseUpdateTime: LARGE_INTEGER
    AccumulatedFrames: UINT
    RectsCoalesced: BOOL
    ProtectedContentMaskedOut: BOOL
    PointerPosition: DXGI_OUTDUPL_POINTER_POSITION
    TotalMetadataBufferSize: UINT
    PointerShapeBufferSize: UINT

class DXGI_MAPPED_RECT(Structure):
    Pitch: INT
    pBits: PFLOAT

class IDXGIObject(_IUnknown):
    def SetPrivateData(self) -> _HRESULT: ...
    def SetPrivateDataInterface(self) -> _HRESULT: ...
    def GetPrivateData(self) -> _HRESULT: ...
    def GetParent(self) -> _HRESULT: ...

class IDXGIDeviceSubObject(IDXGIObject):
    def GetDevice(self) -> _HRESULT: ...

class IDXGIResource(IDXGIDeviceSubObject):
    def GetSharedHandle(self) -> _HRESULT: ...
    def GetUsage(self) -> _HRESULT: ...
    def SetEvictionPriority(self) -> _HRESULT: ...
    def GetEvictionPriority(self) -> _HRESULT: ...

class IDXGISurface(IDXGIDeviceSubObject):
    def GetDesc(self) -> _HRESULT: ...
    def Map(self, __pLockedRect: _Pointer[DXGI_MAPPED_RECT], __MapFlags: UINT) -> _HRESULT: ...
    def Unmap(self) -> _HRESULT: ...

class IDXGIOutputDuplication(IDXGIObject):
    def GetDesc(self) -> None: ...
    def AcquireNextFrame(
        self,
        __TimeoutInMilliseconds: UINT,
        __pFrameInfo: _Pointer[DXGI_OUTDUPL_FRAME_INFO],
        __ppDesktopResource: _Pointer[_Pointer[IDXGIResource]],
    ) -> _HRESULT: ...
    def GetFrameDirtyRects(self) -> _HRESULT: ...
    def GetFrameMoveRects(self) -> _HRESULT: ...
    def GetFramePointerShape(self) -> _HRESULT: ...
    def MapDesktopSurface(self) -> _HRESULT: ...
    def UnMapDesktopSurface(self) -> _HRESULT: ...
    def ReleaseFrame(self) -> _HRESULT: ...

class IDXGIOutput(IDXGIObject):
    def GetDesc(self, __pDesc: _Pointer[DXGI_OUTPUT_DESC]) -> _HRESULT: ...
    def GetDisplayModeList(self) -> _HRESULT: ...
    def FindClosestMatchingMode(self) -> _HRESULT: ...
    def WaitForVBlank(self) -> _HRESULT: ...
    def TakeOwnership(self) -> _HRESULT: ...
    def ReleaseOwnership(self) -> None: ...
    def GetGammaControlCapabilities(self) -> _HRESULT: ...
    def SetGammaControl(self) -> _HRESULT: ...
    def GetGammaControl(self) -> _HRESULT: ...
    def SetDisplaySurface(self) -> _HRESULT: ...
    def GetDisplaySurfaceData(self) -> _HRESULT: ...
    def GetFrameStatistics(self) -> _HRESULT: ...

class IDXGIOutput1(IDXGIOutput):
    def GetDisplayModeList1(self) -> _HRESULT: ...
    def FindClosestMatchingMode1(self) -> _HRESULT: ...
    def GetDisplaySurfaceData1(self) -> _HRESULT: ...
    def DuplicateOutput(
        self, __pDevice: _Pointer[ID3D11Device], __ppOutputDuplication: _Pointer[_Pointer[IDXGIOutputDuplication]]
    ) -> _HRESULT: ...

class IDXGIAdapter(IDXGIObject):
    def EnumOutputs(self, __Output: UINT, __ppOutput: _Pointer[_Pointer[IDXGIOutput]]) -> _HRESULT: ...
    def GetDesc(self) -> _HRESULT: ...
    def CheckInterfaceSupport(self) -> _HRESULT: ...

class IDXGIAdapter1(IDXGIAdapter):
    def GetDesc1(self, __pDesc: _Pointer[DXGI_ADAPTER_DESC1]) -> _HRESULT: ...

class IDXGIFactory(IDXGIObject):
    def EnumAdapters(self) -> _HRESULT: ...
    def MakeWindowAssociation(self) -> _HRESULT: ...
    def GetWindowAssociation(self) -> _HRESULT: ...
    def CreateSwapChain(self) -> _HRESULT: ...
    def CreateSoftwareAdapter(self) -> _HRESULT: ...

class IDXGIFactory1(IDXGIFactory):
    def EnumAdapters1(self, __Adapter: c_uint, __ppAdapter: _Pointer[_Pointer[IDXGIAdapter1]]) -> _HRESULT: ...
    def IsCurrent(self) -> BOOL: ...

def initialize_dxgi_factory() -> _Pointer[IDXGIFactory1]: ...
def discover_dxgi_adapters(dxgi_factory: IDXGIFactory1) -> list[_Pointer[IDXGIAdapter1]]: ...
def describe_dxgi_adapter(dxgi_adapter: IDXGIAdapter1) -> Array[WCHAR]: ...
def discover_dxgi_outputs(dxgi_adapter: IDXGIAdapter) -> list[_Pointer[IDXGIOutput1]]: ...
def describe_dxgi_output(dxgi_output: IDXGIOutput) -> _DXGIOutput: ...
def initialize_dxgi_output_duplication(
    dxgi_output: IDXGIOutput1, d3d_device: _Pointer[ID3D11Device]
) -> _Pointer[IDXGIOutputDuplication]: ...
def get_dxgi_output_duplication_frame(
    dxgi_output_duplication: IDXGIOutputDuplication,
    d3d_device: ID3D11Device,
    process_func: _ProcessFunc[_ProcessFuncRegionArg, _ProcessFuncReturn] | None = ...,
    width: int = ...,
    height: int = ...,
    region: _ProcessFuncRegionArg = ...,
    rotation: int = ...,
) -> _ProcessFuncReturn | None: ...
