module Selenium::WebDriver::PointerActions

def button_action(button, action: nil, device: nil)

def button_action(button, action: nil, device: nil)
  pointer = get_pointer(device)
  pointer.send(action, button)
  tick(pointer)
  self
end

def click(element = nil, device: nil)

def click(element = nil, device: nil)
  move_to(element, device: device) if element
  pointer_down(:left, device: device)
  pointer_up(:left, device: device)
  self
end

def click_and_hold(element = nil, device: nil)

def click_and_hold(element = nil, device: nil)
  move_to(element, device: device) if element
  pointer_down(:left, device: device)
  self
end

def context_click(element = nil, device: nil)

def context_click(element = nil, device: nil)
  move_to(element, device: device) if element
  pointer_down(:right, device: device)
  pointer_up(:right, device: device)
  self
end

def double_click(element = nil, device: nil)

def double_click(element = nil, device: nil)
  move_to(element, device: device) if element
  click(device: device)
  click(device: device)
  self
end

def drag_and_drop(source, target, device: nil)

def drag_and_drop(source, target, device: nil)
  click_and_hold(source, device: device)
  move_to(target, device: device)
  release(device: device)
  self
end

def drag_and_drop_by(source, right_by, down_by, device: nil)

def drag_and_drop_by(source, right_by, down_by, device: nil)
  click_and_hold(source, device: device)
  move_by(right_by, down_by, device: device)
  release(device: device)
  self
end

def get_pointer(device = nil)

def get_pointer(device = nil)
  get_device(device) || pointer_inputs.first
end

def move_by(right_by, down_by, device: nil)

def move_by(right_by, down_by, device: nil)
  pointer = get_pointer(device)
  pointer.create_pointer_move(duration: DEFAULT_MOVE_DURATION,
                              x: Integer(right_by),
                              y: Integer(down_by),
                              origin: Interactions::PointerMove::POINTER)
  tick(pointer)
  self
end

def move_to(element, right_by = nil, down_by = nil, device: nil)

def move_to(element, right_by = nil, down_by = nil, device: nil)
  pointer = get_pointer(device)
  # New actions offset is from center of element
  if right_by || down_by
    size = element.size
    left_offset = (size[:width] / 2).to_i
    top_offset = (size[:height] / 2).to_i
    left = -left_offset + (right_by || 0)
    top = -top_offset + (down_by || 0)
  else
    left = 0
    top = 0
  end
  pointer.create_pointer_move(duration: DEFAULT_MOVE_DURATION,
                              x: left,
                              y: top,
                              element: element)
  tick(pointer)
  self
end

def move_to_location(x, y, device: nil)

def move_to_location(x, y, device: nil)
  pointer = get_pointer(device)
  pointer.create_pointer_move(duration: DEFAULT_MOVE_DURATION,
                              x: Integer(x),
                              y: Integer(y),
                              origin: Interactions::PointerMove::VIEWPORT)
  tick(pointer)
  self
end

def pointer_down(button, device: nil)

def pointer_down(button, device: nil)
  button_action(button, action: :create_pointer_down, device: device)
end

def pointer_up(button, device: nil)

def pointer_up(button, device: nil)
  button_action(button, action: :create_pointer_up, device: device)
end

def release(device: nil)

def release(device: nil)
  pointer_up(:left, device: device)
  self
end