#include <CtrlCore/CtrlCore.h>

#ifdef GUI_GTK

namespace Upp {

extern Event<const TopWindow *, TopWindow::CustomTitleBarMetrics&> custom_titlebar_metrics__;
extern Function<bool (const TopWindow *)> is_custom_titlebar__;
extern Function<Ctrl *(TopWindow *, Color, int)> custom_titlebar_make__;

void TopWindow::CustomBarIcon::Paint(Draw& w)
{
	w.DrawImage(0, 0, HasMouse() ? CtrlCoreImg::GtkBarButtonH() : CtrlCoreImg::GtkBarButton());
	w.DrawImage(0, 0, img);
}

void TopWindow::CustomBarIcon::MouseMove(Point p, dword keyflags)
{
	Refresh();
}

void TopWindow::CustomBarIcon::LeftDown(Point p, dword keyflags)
{
	SetCapture();
}

void TopWindow::CustomBarIcon::LeftUp(Point, dword keyflags)
{
	if(HasMouse())
		Action();
	Refresh();
}

void TopWindow::CustomBarIcon::MouseLeave()
{
	Refresh();
}

void TopWindow::BarCtrl::LeftDouble(Point p, dword keyflags)
{
	WhenAction();
}

void TopWindow::Init()
{
	custom_titlebar_metrics__ = [](const TopWindow *tw, TopWindow::CustomTitleBarMetrics& m) {
		if(!tw->custom_bar)
			return;
		m.height = GetGtkTitleBarHeight(tw);
		m.lm = 0;
		m.rm = 0;
		/*
		Image icon = tw->GetIcon();
		if(!IsNull(icon))
			m.lm = DPI(4) + min(icon.GetWidth(), 32);
		m.rm = (tw->IsZoomable() ? 3 : 1) * GetGtkTitleBarButtonWidth();
		*/
	};

	is_custom_titlebar__ = [](const TopWindow *win) {
		return win->IsCustomTitleBar__();
	};
	
	custom_titlebar_make__ = [=](TopWindow *win, Color bk, int mincy) -> Ctrl * {
		return win->MakeCustomTitleBar__(bk, mincy);
	};
}

int Ctrl::GetGtkTitleBarHeight(const TopWindow *tw)
{
	return max(tw->custom_titlebar_cy, DPI(31));
}

int Ctrl::GetGtkTitleBarButtonWidth()
{
	return DPI(47);
}

void TopWindow::SyncIcons()
{
	minicon.Set(CtrlCoreImg::GtkBarMinimize());
	GtkWindow *w = gtk();
	maxicon.Set(w && gtk_window_is_maximized(w) ? CtrlCoreImg::GtkBarOverlap()
	                                            : CtrlCoreImg::GtkBarMaximize());
	closeicon.Set(CtrlCoreImg::GtkBarClose());
}

void TopWindow::SyncCustomBar()
{
	if(custom_bar_frame) {
	//	custom_bar_frame->Height(GetCustomTitleBarMetrics().height);
		SetCustomBarColor(Nvl(custom_titlebar_bk, SColorFace()));
		auto cm = GetCustomTitleBarMetrics();
		custom_bar->VSizePos().HSizePos(DPI(10), DPI(6));
		RefreshFrame(0, 0, GetRect().Width(), cm.height);
		Size isz = CtrlCoreImg::GtkBarButton().GetSize();
		int y = (cm.height - isz.cy) / 2;
		custom_bar_icons->Width((isz.cx + DPI(8)) * (IsZoomable() ? 3 : 1));
		*custom_bar_icons << closeicon.RightPos(DPI(8), isz.cx).TopPos(y, isz.cy);
		if(IsZoomable()) {
			*custom_bar_icons << minicon.LeftPos(0, isz.cx).TopPos(y, isz.cy);
			*custom_bar_icons << maxicon.LeftPos(isz.cx + DPI(8), isz.cx).TopPos(y, isz.cy);
		}
		else {
			minicon.Remove();
			maxicon.Remove();
		}
		SyncIcons();
	}
}

bool Ctrl::prevent_custombar_drag;

void Ctrl::SetCustomBarDragPrevention()
{ // ugly as hell, but seems to be the only simple way how to prevent window drag in custom titlebar
	static gint p1, p2;
	GtkSettings *gs = gtk_settings_get_default();
	ONCELOCK {
		g_object_get(gs, "gtk-double-click-distance", &p1, "gtk-dnd-drag-threshold", &p2, NULL);
	};
	gint s1 = p1;
	gint s2 = p2;
	if(prevent_custombar_drag)
		s1 = s2 = 1000000; // no drags for you, GtkWindow...
	g_object_set (gs, "gtk-double-click-distance", s1, "gtk-dnd-drag-threshold", s2, NULL);
}

void Ctrl::SyncPreventCustomBarDragPrevention()
{
	TopWindow *tw = dynamic_cast<TopWindow *>(this);
	prevent_custombar_drag = !(tw && !tw->custom_bar_frame); // prevent for popup too to avoid problems with menu
	SetCustomBarDragPrevention();
}

bool TopWindow::IsCustomTitleBar__() const
{
	return custom_bar;
}

void  TopWindow::DoZoom()
{
	GtkWindow *w = gtk();
	if(w) {
		if(gtk_window_is_maximized(w))
			gtk_window_unmaximize(w);
		else
			gtk_window_maximize(w);
	}
}

void  TopWindow::DoMoveWindow()
{
#if GTK_CHECK_VERSION(3, 22, 0)
	if(CurrentEvent.device)
		gdk_window_begin_move_drag_for_device(gdk(), CurrentEvent.device,
		                                      1, CurrentEvent.x_root, CurrentEvent.y_root, CurrentEvent.time);
	else
#endif
		gdk_window_begin_move_drag(gdk(), 1, CurrentEvent.x_root, CurrentEvent.y_root, CurrentEvent.time);
}

Ctrl *TopWindow::MakeCustomTitleBar__(Color bk, int mincy)
{
	if(!custom_bar) {
		custom_bar_frame.Create();
		custom_bar_frame->Transparent();
		custom_bar_icons.Create();
		custom_bar_icons->Transparent();
		custom_bar_frame->AddFrame(*custom_bar_icons);
		custom_bar.Create();
		
		minicon << [=] {
			GtkWindow *w = gtk();
			if(w)
				gtk_window_iconify(w);
		};
		maxicon << [=] {
			DoZoom();
		};
		closeicon << [=] {
			if(IsEnabled()) {
				IgnoreMouseUp();
				WhenClose();
			}
		};
	}
	if(custom_bar) {
		if(&GetFrame(0) != ~custom_bar_frame) {
			RemoveFrame(*custom_bar_frame);
			if(&GetFrame(0) == &NullFrame())
				SetFrame(0, *custom_bar_frame);
			else
				InsertFrame(0, *custom_bar_frame);
		}
		custom_bar_frame->Add(*custom_bar);
	}
	custom_titlebar_bk = bk;
	if(custom_titlebar_cy < 0)
		custom_titlebar_cy = mincy;
	SyncCustomBar();
	return ~custom_bar;
}

}

#endif