import ctypes
import json
from pathlib import Path

import numpy as np
import win32api
import win32con
import win32gui
import win32ui
from PIL import Image, ImageGrab


repo = Path.home() / 'TibiaPilotNG'
result = {}


def image_stats(image):
    array = np.asarray(image)
    return {
        'size': list(image.size),
        'mean': float(array.mean()),
        'nonBlack': float(np.count_nonzero(array) / array.size),
    }


# Bewusst ueber PIL statt pyautogui: pyautogui bringt Tastatur- und
# Maussteuerung mit. Solche Software-Eingaben duerfen im Projekt gar
# nicht erst verfuegbar sein - siehe tests/unit/test_no_software_input.py.
screen = ImageGrab.grab(all_screens=True)
screen.save(repo / '.capture-pil.png')
result['pillow'] = image_stats(screen)

result['monitors'] = []
for index, monitor in enumerate(win32api.EnumDisplayMonitors()):
    rect = monitor[2]
    image = ImageGrab.grab(bbox=rect, all_screens=True)
    image.save(repo / f'.capture-monitor-{index}.png')
    result['monitors'].append({
        'index': index,
        'rect': list(rect),
        **image_stats(image),
    })

game = None


def collect(hwnd, _):
    global game
    if win32gui.IsWindowVisible(hwnd) and win32gui.GetWindowText(hwnd).startswith('Tibia - '):
        game = hwnd


win32gui.EnumWindows(collect, None)
if game:
    left, top, right, bottom = win32gui.GetWindowRect(game)
    width, height = right - left, bottom - top
    window_dc = win32gui.GetWindowDC(game)
    source_dc = win32ui.CreateDCFromHandle(window_dc)
    target_dc = source_dc.CreateCompatibleDC()
    bitmap = win32ui.CreateBitmap()
    bitmap.CreateCompatibleBitmap(source_dc, width, height)
    target_dc.SelectObject(bitmap)
    rendered = ctypes.windll.user32.PrintWindow(game, target_dc.GetSafeHdc(), 2)
    info = bitmap.GetInfo()
    pixels = bitmap.GetBitmapBits(True)
    window = Image.frombuffer(
        'RGB', (info['bmWidth'], info['bmHeight']), pixels, 'raw', 'BGRX', 0, 1
    )
    window.save(repo / '.capture-printwindow.png')
    result['printWindow'] = {'rendered': bool(rendered), **image_stats(window)}
    win32gui.DeleteObject(bitmap.GetHandle())
    target_dc.DeleteDC()
    source_dc.DeleteDC()
    win32gui.ReleaseDC(game, window_dc)

(repo / '.capture-methods.json').write_text(json.dumps(result), encoding='utf-8')
