// wallpaper/window_maker/window_maker.go
package window_maker

import (
	"fmt"
	"sync"
	"syscall"
	"unsafe"
)

// Импорт необходимых DLL
var (
	user32                         = syscall.NewLazyDLL("user32.dll")
	gdi32                          = syscall.NewLazyDLL("gdi32.dll")
	kernel32                       = syscall.NewLazyDLL("kernel32.dll")
	procRegisterClassEx            = user32.NewProc("RegisterClassExW")
	procCreateWindowEx             = user32.NewProc("CreateWindowExW")
	procDefWindowProc              = user32.NewProc("DefWindowProcW")
	procDispatchMessage            = user32.NewProc("DispatchMessageW")
	procGetMessage                 = user32.NewProc("GetMessageW")
	procTranslateMessage           = user32.NewProc("TranslateMessage")
	procShowWindow                 = user32.NewProc("ShowWindow")
	procUpdateWindow               = user32.NewProc("UpdateWindow")
	procSetLayeredWindowAttributes = user32.NewProc("SetLayeredWindowAttributes")
	procSetWindowLongPtr           = user32.NewProc("SetWindowLongPtrW")
	procGetWindowLongPtr           = user32.NewProc("GetWindowLongPtrW")
	procSetWindowPos               = user32.NewProc("SetWindowPos")
	procPostQuitMessage            = user32.NewProc("PostQuitMessage")
	procDestroyWindow              = user32.NewProc("DestroyWindow")
	procLoadCursorW                = user32.NewProc("LoadCursorW")
	procAdjustWindowRectEx         = user32.NewProc("AdjustWindowRectEx")
	procGetSystemMetrics           = user32.NewProc("GetSystemMetrics")
	procGetDC                      = user32.NewProc("GetDC")
	procReleaseDC                  = user32.NewProc("ReleaseDC")
	procRectangle                  = gdi32.NewProc("Rectangle")
	procBeginPaint                 = user32.NewProc("BeginPaint")
	procEndPaint                   = user32.NewProc("EndPaint")
	procCreateSolidBrush           = gdi32.NewProc("CreateSolidBrush")
	procSelectObject               = gdi32.NewProc("SelectObject")
	procDeleteObject               = gdi32.NewProc("DeleteObject")
	procInvalidateRect             = user32.NewProc("InvalidateRect")
)

// Константы Windows API
const (
	WS_OVERLAPPEDWINDOW = 0x00CF0000
	WS_VISIBLE          = 0x10000000
	WS_CAPTION          = 0x00C00000
	WS_SYSMENU          = 0x00080000
	WS_THICKFRAME       = 0x00040000
	WS_MINIMIZEBOX      = 0x00020000
	WS_MAXIMIZEBOX      = 0x00010000
	WS_EX_LAYERED       = 0x00080000
	LWA_ALPHA           = 0x2
	SW_SHOWNORMAL       = 1

	SWP_NOMOVE       = 0x0002
	SWP_NOSIZE       = 0x0001
	SWP_NOZORDER     = 0x0004
	SWP_FRAMECHANGED = 0x0020

	IDC_ARROW = 32512 // Идентификатор стандартного курсора стрелки

	SW_SHOW = 5

	SM_CXSCREEN = 0
	SM_CYSCREEN = 1

	GWL_STYLE   = -16
	GWL_EXSTYLE = -20
)

// RECT структура
type RECT struct {
	Left, Top, Right, Bottom int32
}

// POINT структура
type POINT struct {
	X, Y int32
}

// WNDCLASSEX структура
type WNDCLASSEX struct {
	CbSize        uint32
	Style         uint32
	WndProc       uintptr
	CbClsExtra    int32
	CbWndExtra    int32
	HInstance     syscall.Handle
	HIcon         syscall.Handle
	HCursor       syscall.Handle
	HbrBackground syscall.Handle
	LpszMenuName  *uint16
	LpszClassName *uint16
	HIconSm       syscall.Handle
}

// MSG структура
type MSG struct {
	HWnd    uintptr
	Message uint32
	WParam  uintptr
	LParam  uintptr
	Time    uint32
	Pt      POINT
}

// Window структура представляет окно
type Window struct {
	hwnd        uintptr
	title       string
	width       int
	height      int
	canResize   bool
	mu          sync.Mutex
	shouldClose bool

	// Свойства прямоугольника
	rectX      int
	rectY      int
	rectWidth  int
	rectHeight int
	rectMu     sync.Mutex
}

// Глобальная переменная для текущего окна (предполагается одно окно)
var currentWindow *Window
var windowMutex sync.Mutex

// windowWndProc — процедура окна, обрабатывающая сообщения
func windowWndProc(hwnd uintptr, msg uint32, wParam, lParam uintptr) uintptr {
	switch msg {
	case 0x0010: // WM_CLOSE
		procDestroyWindow.Call(hwnd)
		return 0
	case 0x0002: // WM_DESTROY
		procPostQuitMessage.Call(0)
		return 0
	case 0x000F: // WM_PAINT
		return handleWM_PAINT(hwnd)
	default:
		ret, _, _ := procDefWindowProc.Call(hwnd, uintptr(msg), wParam, lParam)
		return ret
	}
}

// handleWM_PAINT обрабатывает сообщение WM_PAINT
func handleWM_PAINT(hwnd uintptr) uintptr {
	var ps struct {
		Hdc           uintptr
		FErase        int32
		RcPaint       RECT
		RcWindow      RECT
		Flags         uint32
		EraseBkMode   uint32
		FillAttribute uint32
	}
	ret, _, _ := procBeginPaint.Call(hwnd, uintptr(unsafe.Pointer(&ps)))
	if ret == 0 {
		return 0
	}
	hdc := ret

	// Получение экземпляра окна
	windowMutex.Lock()
	win := currentWindow
	windowMutex.Unlock()
	if win == nil {
		procEndPaint.Call(hwnd, uintptr(unsafe.Pointer(&ps)))
		return 0
	}

	// Блокируем доступ к свойствам прямоугольника
	win.rectMu.Lock()
	x := win.rectX
	y := win.rectY
	width := win.rectWidth
	height := win.rectHeight
	win.rectMu.Unlock()

	// Создание кисти (красный цвет: RGB(255,0,0))
	redColor := uintptr(0x0000FF) // COLORREF is 0x00BBGGRR
	hBrush, _, _ := procCreateSolidBrush.Call(redColor)
	if hBrush == 0 {
		procEndPaint.Call(hwnd, uintptr(unsafe.Pointer(&ps)))
		return 0
	}

	// Выбор кисти в контекст устройства (DC)
	oldBrush, _, _ := procSelectObject.Call(hdc, hBrush)

	// Рисование прямоугольника
	procRectangle.Call(hdc, uintptr(x), uintptr(y), uintptr(x+width), uintptr(y+height))

	// Восстановление старой кисти
	procSelectObject.Call(hdc, oldBrush)

	// Удаление созданной кисти
	procDeleteObject.Call(hBrush)

	// Завершение рисования
	procEndPaint.Call(hwnd, uintptr(unsafe.Pointer(&ps)))

	return 0
}

// NewWindow создает новое окно с заданными параметрами и центрирует его на экране
func NewWindow(title string, width, height int, canResize bool) (*Window, error) {
	windowMutex.Lock()
	defer windowMutex.Unlock()

	if currentWindow != nil {
		return nil, fmt.Errorf("поддерживается только одно окно")
	}

	window := &Window{
		title:      title,
		width:      width,
		height:     height,
		canResize:  canResize,
		rectX:      50, // Начальная позиция прямоугольника
		rectY:      50,
		rectWidth:  200, // Начальный размер прямоугольника
		rectHeight: 100,
	}

	// Установка глобальной переменной текущего окна
	currentWindow = window

	// Генерация уникального имени класса
	className := syscall.StringToUTF16Ptr(fmt.Sprintf("GoWindowClass-%p", window))

	// Загрузка стандартного курсора стрелки
	cursor, _, errCursor := procLoadCursorW.Call(0, uintptr(IDC_ARROW))
	if cursor == 0 {
		return nil, fmt.Errorf("не удалось загрузить курсор: %v", errCursor)
	}

	// Определение окна класса
	wc := WNDCLASSEX{
		CbSize:        uint32(unsafe.Sizeof(WNDCLASSEX{})),
		Style:         0,
		WndProc:       syscall.NewCallback(windowWndProc),
		CbClsExtra:    0,
		CbWndExtra:    0,
		HInstance:     0, // NULL
		HIcon:         0, // Значок по умолчанию
		HCursor:       syscall.Handle(cursor),
		HbrBackground: syscall.Handle(5), // COLOR_WINDOW + 1
		LpszMenuName:  nil,
		LpszClassName: className,
		HIconSm:       0,
	}

	// Регистрация класса окна
	ret, _, errReg := procRegisterClassEx.Call(uintptr(unsafe.Pointer(&wc)))
	if ret == 0 {
		return nil, fmt.Errorf("не удалось зарегистрировать класс окна: %v", errReg)
	}

	// Определение стилей окна
	windowStyle := WS_OVERLAPPEDWINDOW | WS_VISIBLE
	if !canResize {
		windowStyle &^= WS_THICKFRAME | WS_MAXIMIZEBOX
	}

	// Преобразование заголовка окна в UTF16
	titleUTF16, err := syscall.UTF16PtrFromString(title)
	if err != nil {
		return nil, fmt.Errorf("ошибка при преобразовании заголовка в UTF16: %v", err)
	}

	// Корректировка размеров окна с учетом стилей
	var rect RECT
	rect.Left = 0
	rect.Top = 0
	rect.Right = int32(width)
	rect.Bottom = int32(height)

	exStyle := uint32(0)
	if canResize {
		exStyle |= WS_EX_LAYERED
	}

	retAdjust, _, errAdjust := procAdjustWindowRectEx.Call(
		uintptr(unsafe.Pointer(&rect)),
		uintptr(windowStyle),
		0, // Без меню
		uintptr(exStyle),
	)
	if retAdjust == 0 {
		return nil, fmt.Errorf("не удалось скорректировать размер окна: %v", errAdjust)
	}

	actualWidth := int(rect.Right - rect.Left)
	actualHeight := int(rect.Bottom - rect.Top)

	// Получение размера экрана
	screenWidth, _, _ := procGetSystemMetrics.Call(SM_CXSCREEN)
	screenHeight, _, _ := procGetSystemMetrics.Call(SM_CYSCREEN)

	// Вычисление позиции для центрирования окна
	x := (int(screenWidth) - actualWidth) / 2
	y := (int(screenHeight) - actualHeight) / 2

	// Создание окна
	hwnd, _, errCreate := procCreateWindowEx.Call(
		uintptr(0), // Расширенные стили окна
		uintptr(unsafe.Pointer(className)),
		uintptr(unsafe.Pointer(titleUTF16)),
		uintptr(windowStyle),
		uintptr(x),
		uintptr(y),
		uintptr(actualWidth),
		uintptr(actualHeight),
		0, // Родительское окно
		0, // Меню
		0, // Дескриптор экземпляра
		0, // Дополнительные данные окна
	)
	if hwnd == 0 {
		return nil, fmt.Errorf("не удалось создать окно: %v", errCreate)
	}

	window.hwnd = hwnd

	return window, nil
}

// Show отображает окно и запускает цикл обработки сообщений в отдельной горутине
func (w *Window) Show() {
	go w.messageLoop()
}

// messageLoop обрабатывает сообщения окна
func (w *Window) messageLoop() {
	var msg MSG
	for {
		ret, _, _ := procGetMessage.Call(
			uintptr(unsafe.Pointer(&msg)),
			0, // HWND (0: сообщения для любых окон текущего потока)
			0,
			0,
		)
		if ret == 0 { // WM_QUIT
			w.mu.Lock()
			w.shouldClose = true
			w.mu.Unlock()
			break
		} else if ret == ^uintptr(0) { // Ошибка (-1)
			break
		} else {
			procTranslateMessage.Call(uintptr(unsafe.Pointer(&msg)))
			procDispatchMessage.Call(uintptr(unsafe.Pointer(&msg)))
		}
	}
}

// ShouldClose проверяет, должно ли окно закрыться
func (w *Window) ShouldClose() bool {
	w.mu.Lock()
	defer w.mu.Unlock()
	return w.shouldClose
}

// Close закрывает окно
func (w *Window) Close() {
	procDestroyWindow.Call(w.hwnd)
}

// Transparented устанавливает прозрачность окна (alpha от 0.0 до 1.0)
func (w *Window) Transparented(alpha float32) error {
	w.mu.Lock()
	defer w.mu.Unlock()

	// Получение текущего расширенного стиля окна
	currentExStyle, _, err := procGetWindowLongPtr.Call(
		w.hwnd,
		uintptr(int(GWL_EXSTYLE)), // Преобразование int к uintptr напрямую
	)
	if currentExStyle == 0 && err != nil && err != syscall.Errno(0) {
		return fmt.Errorf("не удалось получить текущий расширенный стиль окна: %v", err)
	}

	// Установка флага WS_EX_LAYERED
	newExStyle := currentExStyle | WS_EX_LAYERED
	_, _, errSet := procSetWindowLongPtr.Call(
		w.hwnd,
		uintptr(int(GWL_EXSTYLE)), // Преобразование int к uintptr напрямую
		uintptr(newExStyle),
	)
	if errSet != nil && errSet != syscall.Errno(0) {
		return fmt.Errorf("не удалось установить расширенный стиль окна: %v", errSet)
	}

	// Установка прозрачности
	alphaByte := byte(alpha * 255)
	ret, _, errSetAttributes := procSetLayeredWindowAttributes.Call(
		w.hwnd,             // HWND
		0,                  // crKey
		uintptr(alphaByte), // bAlpha
		uintptr(LWA_ALPHA), // dwFlags
	)
	if ret == 0 {
		return fmt.Errorf("не удалось установить атрибуты слоя окна: %v", errSetAttributes)
	}

	return nil
}

// Decorated включает или отключает декорации окна
func (w *Window) Decorated(decorate bool) error {
	w.mu.Lock()
	defer w.mu.Unlock()

	// Получение текущего стиля окна
	currentStyle, _, err := procGetWindowLongPtr.Call(
		w.hwnd,
		uintptr(int(GWL_STYLE)), // Преобразование int к uintptr напрямую
	)
	if currentStyle == 0 && err != nil && err != syscall.Errno(0) {
		return fmt.Errorf("не удалось получить текущий стиль окна: %v", err)
	}

	var newStyle uint32
	if decorate {
		newStyle = uint32(currentStyle | WS_OVERLAPPEDWINDOW)
	} else {
		newStyle = uint32(currentStyle &^ (WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX))
	}

	_, _, errSet := procSetWindowLongPtr.Call(
		w.hwnd,
		uintptr(int(GWL_STYLE)), // Преобразование int к uintptr напрямую
		uintptr(newStyle),
	)
	if errSet != nil && errSet != syscall.Errno(0) {
		return fmt.Errorf("не удалось установить стиль окна: %v", errSet)
	}

	// Обновление стиля окна
	_, _, _ = procSetWindowPos.Call(
		w.hwnd,
		0,
		0,
		0,
		0,
		0,
		uintptr(SWP_NOZORDER|SWP_FRAMECHANGED),
	)

	return nil
}

// Invalidate перерисовывает клиентскую область окна
func (w *Window) Invalidate() error {
	ret, _, err := procInvalidateRect.Call(
		w.hwnd,
		0, // RECT (0: вся клиентская область)
		1, // TRUE: очистить область
	)
	if ret == 0 {
		return fmt.Errorf("не удалось инвалидировать окно: %v", err)
	}
	return nil
}

// SetRectangle устанавливает положение и размер прямоугольника для отрисовки
func (w *Window) SetRectangle(x, y, width, height int) {
	w.rectMu.Lock()
	w.rectX = x
	w.rectY = y
	w.rectWidth = width
	w.rectHeight = height
	w.rectMu.Unlock()

	// Запрос перерисовки окна
	err := w.Invalidate()
	if err != nil {
		fmt.Printf("Ошибка при инвалидировании окна: %v\n", err)
	}
}


# wallpeper/window_maker
window_maker\window_maker.go:380:11: constant -20 overflows uintptr
window_maker\window_maker.go:390:11: constant -20 overflows uintptr
window_maker\window_maker.go:420:11: constant -16 overflows uintptr
window_maker\window_maker.go:435:11: constant -16 overflows uintptr

и при этом окно должно ставиться на середине экрана и размер должекн им ставиться