/*-------------------------------------------------------------------------
 * drawElements Quality Program Tester Core
 * ----------------------------------------
 *
 * Copyright (c) 2016 The Khronos Group Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief X11 using XCB utilities.
 *//*--------------------------------------------------------------------*/

#include "tcuLnxX11Xcb.hpp"
#include "deMemory.h"

namespace tcu
{
namespace lnx
{
namespace x11
{

XcbDisplay::DisplayState XcbDisplay::s_displayState = XcbDisplay::DISPLAY_STATE_UNKNOWN;

bool XcbDisplay::hasDisplay (const char* name)
{
	if (s_displayState == DISPLAY_STATE_UNKNOWN)
	{
		xcb_connection_t *connection = xcb_connect(name, NULL);
		if (connection)
		{
			s_displayState = DISPLAY_STATE_AVAILABLE;
			xcb_disconnect(connection);
		} else
			s_displayState = DISPLAY_STATE_UNAVAILABLE;
	}
	return s_displayState == DISPLAY_STATE_AVAILABLE ? true : false;
}

XcbDisplay::XcbDisplay (EventState& platform, const char* name)
	: DisplayBase	(platform)
{
	m_connection						= xcb_connect(name, NULL);
	const xcb_setup_t		*setup		= xcb_get_setup(m_connection);
	xcb_screen_iterator_t	iterator	= xcb_setup_roots_iterator(setup);
	m_screen							= iterator.data;
}

XcbDisplay::~XcbDisplay (void)
{
	xcb_disconnect (m_connection);
}

void XcbDisplay::processEvents (void)
{
	xcb_generic_event_t *ev;
	while ((ev = xcb_poll_for_event(m_connection)))
	{
		deFree(ev);
		/* Manage your event */
	}
}

XcbWindow::XcbWindow (XcbDisplay& display, int width, int height, xcb_visualid_t* visual)
	: WindowBase	()
	, m_display		(display)
{
	xcb_connection_t*	connection = m_display.getConnection();
	uint32_t			values[2];
	m_window	= xcb_generate_id(connection);
	m_colormap	= xcb_generate_id(connection);

	if (visual == DE_NULL)
		visual = &m_display.getScreen()->root_visual;

	values[0] = m_display.getScreen()->white_pixel;
	values[1] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_PROPERTY_CHANGE;

	xcb_create_window	(
							connection,								// Connection
							XCB_COPY_FROM_PARENT,					// depth (same as root)
							m_window,								// window Id
							display.getScreen()->root,				// parent window
							0, 0,									// x, y
							static_cast<uint16_t >(width),			// width
							static_cast<uint16_t >(height),			// height
							10,										// border_width
							XCB_WINDOW_CLASS_INPUT_OUTPUT,			// class
							*visual,								// visual
							XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK,	// masks
							values									//not used yet
						);

	xcb_create_colormap	(
							connection,
							XCB_COLORMAP_ALLOC_NONE,
							m_colormap,
							m_window,
							*visual
						);

	xcb_alloc_color_reply_t* rep = xcb_alloc_color_reply(connection, xcb_alloc_color(connection, m_colormap, 65535, 0, 0), NULL);
	deFree(rep);
	xcb_flush (connection);
}

XcbWindow::~XcbWindow (void)
{
	xcb_flush (m_display.getConnection());
	xcb_free_colormap(m_display.getConnection(), m_colormap);
	xcb_destroy_window(m_display.getConnection(), m_window);
}

void XcbWindow::setVisibility (bool visible)
{
	if (visible == m_visible)
		return;

	if (visible)
		 xcb_map_window(m_display.getConnection(), m_window);
	else
		xcb_unmap_window(m_display.getConnection(), m_window);

	m_visible = visible;
	xcb_flush (m_display.getConnection());

}

void XcbWindow::processEvents (void)
{
	// A bit of a hack, since we don't really handle all the events.
	m_display.processEvents();
}

void XcbWindow::getDimensions (int* width, int* height) const
{
	xcb_get_geometry_reply_t *geom;
	geom = xcb_get_geometry_reply(m_display.getConnection(), xcb_get_geometry(m_display.getConnection(), m_window), NULL);
	*height = static_cast<int>(geom->height);
	*width = static_cast<int>(geom->width);
	deFree(geom);
}

void XcbWindow::setDimensions (int width, int height)
{
	const uint32_t		values[]	= {static_cast<uint32_t >(width), static_cast<uint32_t >(height)};
	xcb_void_cookie_t	result;
	xcb_connection_t*	display		= m_display.getConnection();
	result = xcb_configure_window(display, m_window, XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values);
	DE_ASSERT(DE_NULL == xcb_request_check(display,result));
	xcb_flush (display);

	for(;;)
	{
		xcb_generic_event_t*	event = xcb_poll_for_event(display);
		int						w, h;
		if(event != DE_NULL)
		{
			if (XCB_PROPERTY_NOTIFY == (event->response_type & ~0x80))
			{
				const xcb_property_notify_event_t* pnEvent = (xcb_property_notify_event_t*)event;
				if (pnEvent->atom == XCB_ATOM_RESOLUTION)
				{
					deFree(event);
					break;
				}
			}
			deFree(event);
		}
		getDimensions (&w,&h);
		if (h==height || w==width)
			break;
	}
}

} // xcb
} // lnx
} // tcu
