using System;
namespace Hiperscan.GtkExtensions
{
    public static class PopupPositioner
    {
        public static void Show(Gtk.Widget popup, Gtk.Widget position_widget, bool adapt_width, int x_offset = 0, int y_offset = 0)
        {
            PopupPositioner.SetWidgetRootWindow(position_widget);
            PopupPositioner.SetPopupWindow(popup);

            if (adapt_width)
                PopupPositioner.PopupRootWindow.WidthRequest = position_widget.Allocation.Width;

            if (PopupPositioner.WidgetRootWindow.GdkWindow == null)
                return;

            int screen_x = PopupPositioner.WidgetRootWindow.Screen.Width;
            int screen_y = PopupPositioner.WidgetRootWindow.Screen.Height;


            position_widget.TranslateCoordinates(PopupPositioner.WidgetRootWindow, 0, 0, out int x, out int y);
            PopupPositioner.WidgetRootWindow.GdkWindow.GetPosition(out int tmp_x, out int tmp_y);

            x += tmp_x;
            y += tmp_y + position_widget.Allocation.Height;

            Gtk.Menu menu = popup as Gtk.Menu;
            if (menu != null)
            {
                menu.ShowAll();
                menu.Popup();
            }
                
            PopupPositioner.PopupRootWindow.ShowAll();

            bool add_x_offset = true;
            bool add_y_offset = true;

            if (x + PopupPositioner.PopupRootWindow.Allocation.Width > screen_x)
            {
                x = screen_x - PopupPositioner.PopupRootWindow.Allocation.Width;
                add_x_offset = false;
            }

            if (y + PopupPositioner.PopupRootWindow.Allocation.Height > screen_y)
            {
                y = y - position_widget.Allocation.Height - PopupPositioner.PopupRootWindow.Allocation.Height;
                add_y_offset = false;
            }

            PopupPositioner.PopupRootWindow.Move(x + (add_x_offset? x_offset : -x_offset), 
                                                  y + (add_y_offset? y_offset : -y_offset));


        }

        private static void SetWidgetRootWindow (Gtk.Widget widget)
        {
            if (widget.Parent == null)
            {
                PopupPositioner.WidgetRootWindow = widget as Gtk.Window;
                return;
            }

            SetWidgetRootWindow(widget.Parent);
        }

        private static void SetPopupWindow(Gtk.Widget widget)
        {
            if (widget.Parent == null)
            {
                PopupPositioner.PopupRootWindow = widget as Gtk.Window;
                return;
            }

            SetPopupWindow(widget.Parent);
        }

        private static Gtk.Window WidgetRootWindow { get; set; }
        private static Gtk.Window PopupRootWindow { get; set; }

    }
}
