// window_maker/window_maker.go
package window_maker

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

var (
	user32   = syscall.NewLazyDLL("user32.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")
)

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 // Как в Windows API
)

// GWL_STYLE и GWL_EXSTYLE определяются как переменные типа int
var (
	GWL_STYLE   = -16
	GWL_EXSTYLE = -20
)

type Window struct {
	hwnd      uintptr
	title     string
	width     int
	height    int
	canResize bool
	mu        sync.Mutex
}

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
}

var (
	classCounter = 0
)

// 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
	default:
		ret, _, _ := procDefWindowProc.Call(hwnd, uintptr(msg), wParam, lParam)
		return ret
	}
}

// NewWindow создает новое окно с заданными параметрами.
func NewWindow(title string, width, height int, canResize bool) (*Window, error) {
	window := &Window{
		title:     title,
		width:     width,
		height:    height,
		canResize: canResize,
	}

	// Генерация уникального имени класса
	className := fmt.Sprintf("WindowClass-%d", classCounter)
	classCounter++

	classNameUTF16, err := syscall.UTF16PtrFromString(className)
	if err != nil {
		return nil, fmt.Errorf("ошибка при преобразовании имени класса в UTF16: %v", err)
	}

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

	// Определение процедуры окна
	wndProc := syscall.NewCallback(windowWndProc)

	windowClass := &WNDCLASSEX{
		CbSize:        uint32(unsafe.Sizeof(WNDCLASSEX{})),
		Style:         0,
		WndProc:       wndProc,
		CbClsExtra:    0,
		CbWndExtra:    0,
		HInstance:     syscall.Handle(uintptr(0)),
		HIcon:         0,
		HCursor:       syscall.Handle(cursor),
		HbrBackground: syscall.Handle(5), // COLOR_WINDOW + 1
		LpszMenuName:  nil,
		LpszClassName: classNameUTF16,
		HIconSm:       0,
	}

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

	windowStyle := WS_OVERLAPPEDWINDOW | WS_VISIBLE
	if !canResize {
		windowStyle &^= WS_THICKFRAME | WS_MAXIMIZEBOX
	}

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

	hwnd, _, errCreate := procCreateWindowEx.Call(
		0,
		uintptr(unsafe.Pointer(classNameUTF16)),
		uintptr(unsafe.Pointer(titleUTF16)),
		uintptr(windowStyle),
		100, 100, // x, y
		uintptr(width),
		uintptr(height),
		0,
		0,
		0,
		0,
	)

	if hwnd == 0 {
		return nil, fmt.Errorf("не удалось создать окно: %v", errCreate)
	}

	window.hwnd = hwnd

	return window, nil
}

// Show отображает окно и запускает цикл обработки сообщений до закрытия окна.
func (w *Window) Show() {
	// Показываем окно
	procShowWindow.Call(w.hwnd, SW_SHOWNORMAL)
	procUpdateWindow.Call(w.hwnd)

	// Цикл обработки сообщений
	for {
		var msg struct {
			hwnd    uintptr
			message uint32
			wParam  uintptr
			lParam  uintptr
			time    uint32
			pt      struct{ x, y int32 }
		}

		ret, _, _ := procGetMessage.Call(uintptr(unsafe.Pointer(&msg)), 0, 0, 0)
		if ret == 0 || ret == 0xFFFFFFFF { // WM_QUIT или ошибка
			break
		}
		procTranslateMessage.Call(uintptr(unsafe.Pointer(&msg)))
		procDispatchMessage.Call(uintptr(unsafe.Pointer(&msg)))
	}
}

// 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(GWL_EXSTYLE))
	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(GWL_EXSTYLE), uintptr(newExStyle))
	if errSet != syscall.Errno(0) && errSet != nil {
		return fmt.Errorf("не удалось установить расширенный стиль окна: %v", errSet)
	}

	// Установка прозрачности
	alphaByte := byte(alpha * 255)
	ret, _, errSetAttributes := procSetLayeredWindowAttributes.Call(w.hwnd, 0, uintptr(alphaByte), uintptr(LWA_ALPHA))
	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(GWL_STYLE))
	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(GWL_STYLE), uintptr(newStyle))
	if errSet != syscall.Errno(0) && errSet != nil {
		return fmt.Errorf("не удалось установить стиль окна: %v", errSet)
	}

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

	return nil
}

// ApplyShader применяет шейдер к окну (заглушка, требует реализации).
func (w *Window) ApplyShader(shaderFunc func(x, y int) uint32) error {
	// Реализация применения шейдера требует работы с графическими API и буферами пикселей
	return fmt.Errorf("ApplyShader не реализован")
}

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


// main.go
package main

import (
	"fmt"
	"wallpeper/window_maker" // Замените "wallpeper/window_maker" на фактический путь к вашему модулю
)

func main() {
	// Создание нового окна
	window, err := window_maker.NewWindow("Моё Окно", 800, 600, true)
	if err != nil {
		panic(fmt.Sprintf("Ошибка при создании окна: %v", err))
	}

	// Установка прозрачности окна (например, 50% прозрачность)
	err = window.Transparented(0.8)
	if err != nil {
		panic(fmt.Sprintf("Ошибка при установке прозрачности: %v", err))
	}

	// Отключение декораций окна
	err = window.Decorated(true)
	if err != nil {
		panic(fmt.Sprintf("Ошибка при отключении декораций: %v", err))
	}

	// Отображение окна и запуск цикла обработки сообщений
	window.Show()

	fmt.Println("Окно закрыто. Программа завершена.")
}



размер окна не ставится испправь и оуно работает не стабильно онон иногра протсо зависает и не отвечает также реализуй чтоы было 

for !window.ShoudClose() { и чтобы тут можно было управлять всем тут  ставить прозрачность окна и тут же отрисовку шейдеров и всяких обьектов } - это как в opengl go реализуй

по умолчанию сделай так чтобы окно ставилось по середине экрана также реализуй отрисовку простых обьектов то есть покеа что просто крадрат и чтобы можно было выбирать ему позицию на окне и размер