// main.c - чистая версия для FreeBSD
#ifndef __linux__
#define __linux__ 1  // для совместимости
#endif
#ifndef _LINUX
#define _LINUX 1
#endif

#ifndef _SAPI
#define _SAPI SciterAPI
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

// X11, OpenGL и FreeBSD специфичные заголовки
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#include <X11/extensions/Xcomposite.h>
#include <GL/glx.h>

#include <uchar.h>

// Sciter C API (не C++!)
#include <sciter-x.h>

// Глобальные переменные X11/GLX
Display *dpy = NULL;
Window root_win = 0;
Window comp_win = 0;
int screen = 0;
int screen_width = 0;
int screen_height = 0;

GLXContext glx_ctx = NULL;
GLXFBConfig fb_config = 0;

Atom wm_delete_window = 0;

// Окно Sciter (структура вместо класса)
HWINDOW g_sciter_hwnd = NULL;

// -------------------------------------------------------------
// Инициализация X11
// -------------------------------------------------------------
void init_x11(void) {
    dpy = XOpenDisplay(NULL);
    if (!dpy) {
        fprintf(stderr, "Ошибка: не могу открыть дисплей\n");
        exit(1);
    }

    screen = DefaultScreen(dpy);
    root_win = DefaultRootWindow(dpy);

    screen_width = WidthOfScreen(DefaultScreenOfDisplay(dpy));
    screen_height = HeightOfScreen(DefaultScreenOfDisplay(dpy));

    XSetWindowAttributes attrs;
    attrs.override_redirect = True;
    attrs.background_pixel = 0;
    attrs.border_pixel = 0;
    attrs.event_mask = ExposureMask | KeyPressMask | StructureNotifyMask | KeyReleaseMask;

    comp_win = XCreateWindow(dpy, root_win,
                             0, 0, screen_width, screen_height, 0,
                             CopyFromParent, InputOutput, CopyFromParent,
                             CWOverrideRedirect | CWBackPixel | CWBorderPixel | CWEventMask,
                             &attrs);

    // Установка состояния окна (поверх всех и полноэкранный режим)
    Atom net_wm_state = XInternAtom(dpy, "_NET_WM_STATE", False);
    Atom net_wm_state_above = XInternAtom(dpy, "_NET_WM_STATE_ABOVE", False);
    Atom net_wm_state_fullscreen = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);

    Atom states[] = { net_wm_state_above, net_wm_state_fullscreen };
    XChangeProperty(dpy, comp_win, net_wm_state, XA_ATOM, 32,
                    PropModeReplace, (unsigned char *)states, 2);

    // Обработка закрытия окна
    wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
    XSetWMProtocols(dpy, comp_win, &wm_delete_window, 1);

    XMapWindow(dpy, comp_win);
    XRaiseWindow(dpy, comp_win);
    XFlush(dpy);

    printf("Окно создано: 0x%lx (%dx%d)\n", comp_win, screen_width, screen_height);
}

// -------------------------------------------------------------
// Инициализация GLX для FreeBSD
// -------------------------------------------------------------
void init_glx(void) {
    XWindowAttributes win_attrs;
    XGetWindowAttributes(dpy, comp_win, &win_attrs);
    Visual *window_visual = win_attrs.visual;
    VisualID window_visual_id = XVisualIDFromVisual(window_visual);

    // Атрибуты для GLX
    int fb_attribs[] = {
        GLX_RENDER_TYPE,   GLX_RGBA_BIT,
        GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
        GLX_RED_SIZE,      8,
        GLX_GREEN_SIZE,    8,
        GLX_BLUE_SIZE,     8,
        GLX_ALPHA_SIZE,    8,
        GLX_DEPTH_SIZE,    24,
        GLX_DOUBLEBUFFER,  True,
        None
    };

    int num_fb;
    GLXFBConfig *fb_configs = glXChooseFBConfig(dpy, screen, fb_attribs, &num_fb);
    if (!fb_configs) {
        fprintf(stderr, "Ошибка: не удалось получить FBConfig\n");
        exit(1);
    }

    // Поиск совместимого FBConfig
    GLXFBConfig compatible_config = 0;
    for (int i = 0; i < num_fb; i++) {
        int visual_id = 0;
        glXGetFBConfigAttrib(dpy, fb_configs[i], GLX_VISUAL_ID, &visual_id);
        if ((VisualID)visual_id == window_visual_id) {
            compatible_config = fb_configs[i];
            break;
        }
    }

    if (!compatible_config) {
        compatible_config = fb_configs[0];
        printf("Предупреждение: используется несовместимый FBConfig\n");
    }

    fb_config = compatible_config;
    XFree(fb_configs);

    // Создание контекста OpenGL
    glx_ctx = glXCreateNewContext(dpy, fb_config, GLX_RGBA_TYPE, NULL, True);
    if (!glx_ctx) {
        fprintf(stderr, "Ошибка: не удалось создать GLX контекст\n");
        exit(1);
    }

    // Делаем контекст текущим
    if (!glXMakeCurrent(dpy, comp_win, glx_ctx)) {
        fprintf(stderr, "Ошибка: glXMakeCurrent не удался\n");
        exit(1);
    }

    printf("GLX инициализирован. OpenGL: %s\n", glGetString(GL_VERSION));
}

// -------------------------------------------------------------
// Функции обратного вызова Sciter
// -------------------------------------------------------------
// Вызывается при необходимости перерисовки окна
void sciter_on_paint(HWINDOW hwnd, UINT_PTR reserved) {
    // Sciter сам обрабатывает отрисовку через OpenGL
    // Просто вызываем обновление
    SciterUpdateWindow(hwnd);
}

// -------------------------------------------------------------
// Инициализация Sciter
// -------------------------------------------------------------
void init_sciter(void) {
    // Устанавливаем графический слой OpenGL (через Skia)
    SciterSetOption(NULL, SCITER_SET_GFX_LAYER, GFX_LAYER_SKIA_OPENGL);

    // Включаем возможности для скриптов
    SciterSetOption(NULL, SCITER_SET_SCRIPT_RUNTIME_FEATURES,
                      ALLOW_FILE_IO | ALLOW_SOCKET_IO | ALLOW_EVAL | ALLOW_SYSINFO);

    // Создаем окно Sciter (без WinAPI, через X11)
    RECT frame_rect = {0, 0, screen_width, screen_height};

    g_sciter_hwnd = SciterCreateWindow(
        SW_MAIN | SW_ENABLE_DEBUG,
        &frame_rect,
        NULL,
        NULL,
        NULL
    );

    if (!g_sciter_hwnd) {
        fprintf(stderr, "Ошибка: не удалось создать Sciter окно\n");
        exit(1);
    }

    // Устанавливаем обработчик отрисовки
    //sciter_callback(g_sciter_hwnd, SCITER_CB_PAINT, (void*)sciter_on_paint);

    // HTML контент
    const char *html =
        "<!DOCTYPE html>"
        "<html><head><meta charset='UTF-8'><style>"
        "html { background: transparent; overflow: hidden; }"
        "body { background: rgba(26,26,26,0.9); color:#e0e0e0; "
        "display:flex; justify-content:center; align-items:center; "
        "height:100vh; margin:0; font-family:system-ui; }"
        ".panel { background:#2b2b2b; border-radius:16px; padding:32px; "
        "text-align:center; box-shadow:0 8px 20px rgba(0,0,0,0.3); }"
        "h1 { color:#fff; margin-bottom:16px; }"
        "button { background:#0060df; color:#fff; border:none; border-radius:6px; "
        "padding:12px 24px; margin:8px; cursor:pointer; font-size:16px; "
        "transition:background 0.2s; }"
        "button:hover { background:#003eaa; }"
        "#status { margin-top:20px; color:#00ff9d; font-weight:bold; }"
        "</style></head>"
        "<body><div class='panel'><h1>Calista + Sciter</h1>"
        "<p>Sciter работает через OpenGL на FreeBSD!</p>"
        "<button onclick='document.getElementById(\"status\").innerText=\"✓ Готово!\"'>"
        "Нажми меня</button>"
        "<div id='status'>Система готова</div>"
        "</div></body></html>";

    // Загружаем HTML
    SciterLoadHtml(g_sciter_hwnd, html, (UINT)strlen(html), "/");

    printf("Sciter инициализирован и HTML загружен\n");
}

// -------------------------------------------------------------
// Обновление позиции окна Sciter
// -------------------------------------------------------------
void update_sciter_window_size(int width, int height) {
    if (g_sciter_hwnd) {
        RECT rect = {0, 0, width, height};
        //SciterSetWindowRect(g_sciter_hwnd, &rect);
    }
}

// -------------------------------------------------------------
// Главный цикл обработки событий
// -------------------------------------------------------------
void main_loop(void) {
    XEvent ev;
    bool running = true;

    printf("Композитор запущен. Нажмите Q или Escape для выхода.\n");

    while (running) {
        // Обработка событий X11
        while (XPending(dpy) > 0) {
            XNextEvent(dpy, &ev);

            switch (ev.type) {
                case Expose:
                    if (ev.xexpose.count == 0) {
                        // Обновляем Sciter при необходимости
                        SciterUpdateWindow(g_sciter_hwnd);
                    }
                    break;

                case KeyPress:
                {
                    char key_str[32];
                    KeySym keysym;
                    XLookupString(&ev.xkey, key_str, sizeof(key_str), &keysym, NULL);

                    // Выход по Q или Escape
                    if (keysym == XK_q || keysym == XK_Q || keysym == XK_Escape) {
                        printf("Выход по запросу пользователя\n");
                        running = false;
                    }
                    break;
                }

                case ConfigureNotify:
                    screen_width = ev.xconfigure.width;
                    screen_height = ev.xconfigure.height;
                    update_sciter_window_size(screen_width, screen_height);
                    break;

                case ClientMessage:
                    if ((Atom)ev.xclient.data.l[0] == wm_delete_window) {
                        printf("Получен WM_DELETE_WINDOW\n");
                        running = false;
                    }
                    break;

                case DestroyNotify:
                    printf("Окно разрушено\n");
                    running = false;
                    break;
            }
        }

        // Обновляем Sciter
        SciterUpdateWindow(g_sciter_hwnd);

        // Небольшая задержка для снижения нагрузки на CPU
        usleep(10000); // 10ms
    }
}

// -------------------------------------------------------------
// Очистка ресурсов
// -------------------------------------------------------------
void cleanup(void) {
    if (g_sciter_hwnd) {
        //SciterCloseWindow(g_sciter_hwnd);
        g_sciter_hwnd = NULL;
    }

    if (glx_ctx) {
        glXMakeCurrent(dpy, None, NULL);
        glXDestroyContext(dpy, glx_ctx);
        glx_ctx = NULL;
    }

    if (comp_win) {
        XDestroyWindow(dpy, comp_win);
        comp_win = 0;
    }

    if (dpy) {
        XCloseDisplay(dpy);
        dpy = NULL;
    }

    printf("Ресурсы освобождены\n");
}

// -------------------------------------------------------------
// Точка входа
// -------------------------------------------------------------
int main(int argc, char **argv) {
    // Игнорируем аргументы
    (void)argc;
    (void)argv;

    printf("Запуск Calista композитора для FreeBSD\n");

    init_x11();
    init_glx();
    init_sciter();

    main_loop();
    cleanup();

    return 0;
}