// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build linux,!android

#include "_cgo_export.h"
#include <EGL/egl.h>
#include <stdio.h>
#include <stdlib.h>

EGLConfig e_config;
EGLContext e_ctx;
EGLDisplay e_dpy;
Colormap x_colormap;
Display *x_dpy;
XVisualInfo *x_visual_info;
Window x_root;

// TODO: share code with eglErrString
char *
eglGetErrorStr() {
	switch (eglGetError()) {
	case EGL_SUCCESS:
		return "EGL_SUCCESS";
	case EGL_NOT_INITIALIZED:
		return "EGL_NOT_INITIALIZED";
	case EGL_BAD_ACCESS:
		return "EGL_BAD_ACCESS";
	case EGL_BAD_ALLOC:
		return "EGL_BAD_ALLOC";
	case EGL_BAD_ATTRIBUTE:
		return "EGL_BAD_ATTRIBUTE";
	case EGL_BAD_CONFIG:
		return "EGL_BAD_CONFIG";
	case EGL_BAD_CONTEXT:
		return "EGL_BAD_CONTEXT";
	case EGL_BAD_CURRENT_SURFACE:
		return "EGL_BAD_CURRENT_SURFACE";
	case EGL_BAD_DISPLAY:
		return "EGL_BAD_DISPLAY";
	case EGL_BAD_MATCH:
		return "EGL_BAD_MATCH";
	case EGL_BAD_NATIVE_PIXMAP:
		return "EGL_BAD_NATIVE_PIXMAP";
	case EGL_BAD_NATIVE_WINDOW:
		return "EGL_BAD_NATIVE_WINDOW";
	case EGL_BAD_PARAMETER:
		return "EGL_BAD_PARAMETER";
	case EGL_BAD_SURFACE:
		return "EGL_BAD_SURFACE";
	case EGL_CONTEXT_LOST:
		return "EGL_CONTEXT_LOST";
	}
	return "unknown EGL error";
}

void
startDriver() {
	x_dpy = XOpenDisplay(NULL);
	if (!x_dpy) {
		fprintf(stderr, "XOpenDisplay failed\n");
		exit(1);
	}
	e_dpy = eglGetDisplay(x_dpy);
	if (!e_dpy) {
		fprintf(stderr, "eglGetDisplay failed: %s\n", eglGetErrorStr());
		exit(1);
	}
	EGLint e_major, e_minor;
	if (!eglInitialize(e_dpy, &e_major, &e_minor)) {
		fprintf(stderr, "eglInitialize failed: %s\n", eglGetErrorStr());
		exit(1);
	}
	if (!eglBindAPI(EGL_OPENGL_ES_API)) {
		fprintf(stderr, "eglBindAPI failed: %s\n", eglGetErrorStr());
		exit(1);
	}

	static const EGLint attribs[] = {
		EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
		EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
		EGL_BLUE_SIZE, 8,
		EGL_GREEN_SIZE, 8,
		EGL_RED_SIZE, 8,
		EGL_DEPTH_SIZE, 16,
		EGL_CONFIG_CAVEAT, EGL_NONE,
		EGL_NONE
	};
	EGLint num_configs;
	if (!eglChooseConfig(e_dpy, attribs, &e_config, 1, &num_configs)) {
		fprintf(stderr, "eglChooseConfig failed: %s\n", eglGetErrorStr());
		exit(1);
	}
	EGLint vid;
	if (!eglGetConfigAttrib(e_dpy, e_config, EGL_NATIVE_VISUAL_ID, &vid)) {
		fprintf(stderr, "eglGetConfigAttrib failed: %s\n", eglGetErrorStr());
		exit(1);
	}

	XVisualInfo visTemplate;
	visTemplate.visualid = vid;
	int num_visuals;
	x_visual_info = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
	if (!x_visual_info) {
		fprintf(stderr, "XGetVisualInfo failed\n");
		exit(1);
	}

	x_root = RootWindow(x_dpy, DefaultScreen(x_dpy));
	x_colormap = XCreateColormap(x_dpy, x_root, x_visual_info->visual, AllocNone);
	if (!x_colormap) {
		fprintf(stderr, "XCreateColormap failed\n");
		exit(1);
	}

	static const EGLint ctx_attribs[] = {
		EGL_CONTEXT_CLIENT_VERSION, 2,
		EGL_NONE
	};
	e_ctx = eglCreateContext(e_dpy, e_config, EGL_NO_CONTEXT, ctx_attribs);
	if (!e_ctx) {
		fprintf(stderr, "eglCreateContext failed: %s\n", eglGetErrorStr());
		exit(1);
	}
}

void
processEvents() {
	while (XPending(x_dpy)) {
		XEvent ev;
		XNextEvent(x_dpy, &ev);
		switch (ev.type) {
		case ButtonPress:
		case ButtonRelease:
			onMouse(ev.xbutton.window, ev.xbutton.x, ev.xbutton.y, ev.xbutton.state, ev.xbutton.button,
				ev.type == ButtonPress ? 1 : 2);
			break;
		case MotionNotify:
			onMouse(ev.xmotion.window, ev.xmotion.x, ev.xmotion.y, ev.xmotion.state, 0, 0);
			break;
		case Expose:
			// A non-zero Count means that there are more expose events coming. For
			// example, a non-rectangular exposure (e.g. from a partially overlapped
			// window) will result in multiple expose events whose dirty rectangles
			// combine to define the dirty region. Go's paint events do not provide
			// dirty regions, so we only pass on the final X11 expose event.
			if (ev.xexpose.count == 0) {
				onExpose(ev.xexpose.window);
			}
			break;
		case ConfigureNotify:
			onResize(ev.xconfigure.window, ev.xconfigure.width, ev.xconfigure.height);
			break;
		}
	}
}

void
makeCurrent(uintptr_t surface) {
	EGLSurface surf = (EGLSurface)(surface);
	if (!eglMakeCurrent(e_dpy, surf, surf, e_ctx)) {
		fprintf(stderr, "eglMakeCurrent failed: %s\n", eglGetErrorStr());
		exit(1);
	}
}

void
swapBuffers(uintptr_t surface) {
	EGLSurface surf = (EGLSurface)(surface);
	if (!eglSwapBuffers(e_dpy, surf)) {
		fprintf(stderr, "eglSwapBuffers failed: %s\n", eglGetErrorStr());
		exit(1);
	}
}

uintptr_t
doNewWindow(int width, int height) {
	XSetWindowAttributes attr;
	attr.colormap = x_colormap;
	attr.event_mask =
		ButtonPressMask |
		ButtonReleaseMask |
		PointerMotionMask |
		ButtonMotionMask |
		ExposureMask |
		StructureNotifyMask;
	Window win = XCreateWindow(
		x_dpy, x_root, 0, 0, width, height, 0, x_visual_info->depth, InputOutput,
		x_visual_info->visual, CWColormap | CWEventMask, &attr);
	XSizeHints sizehints;
	sizehints.width = width;
	sizehints.height = height;
	sizehints.flags = USSize;
	XSetNormalHints(x_dpy, win, &sizehints);
	XSetStandardProperties(x_dpy, win, "App", "App", None, (char **)NULL, 0, &sizehints);
	return win;
}

uintptr_t
doShowWindow(uintptr_t id) {
	Window win = (Window)(id);
	XMapWindow(x_dpy, win);
	EGLSurface surf = eglCreateWindowSurface(e_dpy, e_config, win, NULL);
	if (!surf) {
		fprintf(stderr, "eglCreateWindowSurface failed: %s\n", eglGetErrorStr());
		exit(1);
	}
	return (uintptr_t)(surf);
}
