# Gtk imports
import gi

gi.require_version('Gdk', '3.0')

from gi.repository import Gdk
from gi.repository import GObject

# Python imports
import os

# Application imports


class Dragging:
    def __init__(self):
        # higher values make movement more performant
        # lower values make movement smoother
        self.SENSITIVITY = 1
        self.desktop     = None
        self.EvMask      = Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.BUTTON1_MOTION_MASK
        self.offsetx     = 0
        self.offsety     = 0
        self.px          = 0
        self.py          = 0
        self.maxx        = 0
        self.maxy        = 0

    def connectEvents(self, desktop, widget):
        self.desktop = desktop
        widget.set_events(self.EvMask)
        widget.connect("button_press_event", self.press_event)
        widget.connect("motion_notify_event", self.draggingEvent)
        widget.show()

    def press_event(self, w, event):
        if event.button == 1:
            p = w.get_parent()
            # offset == distance of parent widget from edge of screen ...
            self.offsetx, self.offsety =  p.get_window().get_position()
            # plus distance from pointer to edge of widget
            self.offsetx += event.x
            self.offsety += event.y
            # self.maxx, self.maxy both relative to the parent
            # note that we're rounding down now so that these max values don't get
            # rounded upward later and push the widget off the edge of its parent.
            self.maxx = self.RoundDownToMultiple(p.get_allocation().width - w.get_allocation().width, self.SENSITIVITY)
            self.maxy = self.RoundDownToMultiple(p.get_allocation().height - w.get_allocation().height, self.SENSITIVITY)


    def draggingEvent(self, widget, event):
        # x_root,x_root relative to screen
        # x,y relative to parent (fixed widget)
        # self.px,self.py stores previous values of x,y

        # get starting values for x,y
        x = event.x_root - self.offsetx
        y = event.y_root - self.offsety
        # make sure the potential coordinates x,y:
        #   1) will not push any part of the widget outside of its parent container
        #   2) is a multiple of self.SENSITIVITY
        x = self.RoundToNearestMultiple(self.Max(self.Min(x, self.maxx), 0), self.SENSITIVITY)
        y = self.RoundToNearestMultiple(self.Max(self.Min(y, self.maxy), 0), self.SENSITIVITY)
        if x != self.px or y != self.py:
            self.px = x
            self.py = y
            self.desktop.move(widget, x, y)

    def Min(self, a, b):
        if  b < a:
            return b
        return a

    def Max(self, a, b):
        if b > a:
            return b
        return a

    def RoundDownToMultiple(self, i, m):
        return i/m*m

    def RoundToNearestMultiple(self, i, m):
        if i % m > m / 2:
            return (i/m+1)*m
        return i/m*m
