module Kz
  module Utils
    module_function
    def move_to(base, target)
      window = base.window
      screen = window.screen
      num = screen.get_monitor(window)
      monitor = screen.monitor_geometry(num)
      window_x, window_y = window.origin
      window_width, window_height = window.size
      target_width, target_height = target.size_request

      args = [window_x, window_y, window_width, window_height]
      args.concat([target_width, target_height])
      args.concat([screen.width, screen.height])
      x, y = yield(*args)

      target.move(x, y)
    end

    def compute_left_x(base_x)
      [base_x, 0].max
    end

    def compute_right_x(base_x, base_width, target_width, max_x)
      right = base_x + base_width - target_width
      [[right, max_x - target_width].min, 0].max
    end

    def compute_top_y(base_y)
      [base_y, 0].max
    end

    def compute_bottom_y(base_y, base_height, target_height, max_y)
      bottom = base_y + base_height - target_height
      [[bottom, max_y - target_height].min, 0].max
    end

    def move_to_top_left(base, target)
      move_to(base, target) do |bx, by, bw, bh, tw, th, sw, sh|
        [compute_left_x(bx), compute_top_y(by)]
      end
    end

    def move_to_top_left_outer(base, target)
      move_to(base, target) do |bx, by, bw, bh, tw, th, sw, sh|
        [compute_left_x(bx), compute_top_y(by) - th]
      end
    end

    def move_to_top_right(base, target)
      move_to(base, target) do |bx, by, bw, bh, tw, th, sw, sh|
        [compute_right_x(bx, bw, tw, sw), compute_top_y(by)]
      end
    end

    def move_to_top_right_outer(base, target)
      move_to(base, target) do |bx, by, bw, bh, tw, th, sw, sh|
        [compute_right_x(bx, bw, tw, sw), compute_top_y(by) - th]
      end
    end

    def move_to_bottom_left(base, target)
      move_to(base, target) do |bx, by, bw, bh, tw, th, sw, sh|
        [compute_left_x(bx), compute_bottom_y(by, bh, th, sh)]
      end
    end

    def move_to_bottom_left_outer(base, target)
      move_to(base, target) do |bx, by, bw, bh, tw, th, sw, sh|
        [compute_left_x(bx), compute_bottom_y(by, bh, th, sh) + th]
      end
    end

    def move_to_bottom_right(base, target)
      move_to(base, target) do |bx, by, bw, bh, tw, th, sw, sh|
        [compute_right_x(bx, bw, tw, sw),
         compute_bottom_y(by, bh, th, sh)]
      end
    end

    def move_to_bottom_right(base, target)
      move_to(base, target) do |bx, by, bw, bh, tw, th, sw, sh|
        [compute_right_x(bx, bw, tw, sw),
         compute_bottom_y(by, bh, th, sh) + th]
      end
    end
  end
end
