# Copyright (C) 2016 Google Inc.
# Licensed under http://www.apache.org/licenses/LICENSE-2.0 <see LICENSE file>

"""Utility function for selenium"""

import time
import logging

# pylint: disable=import-error
from selenium.webdriver.support import expected_conditions as EC
# pylint: disable=import-error
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common import action_chains
from selenium.common import exceptions

from lib import exception
from lib import constants

logger = logging.getLogger(__name__)


def hover_over_element(driver, element):
  """Moves the mouse pointer to the element and hovers"""
  action_chains.ActionChains(driver).move_to_element(element).perform()


def wait_until_stops_moving(element):
  """Waits until the element stops moving

  Args:
      selenium.webdriver.remote.webelement.WebElement
  """

  prev_location = None
  timer_begin = time.time()

  while prev_location != element.location:
    prev_location = element.location
    time.sleep(0.1)

    if time.time() - timer_begin > constants.ux.ELEMENT_MOVING_TIMEOUT:
      raise exception.ElementMovingTimeout


def get_when_visible(driver, locator):
  """
  Args:
    driver (base.CustomDriver)
    locator (tuple)

  Returns:
      selenium.webdriver.remote.webelement.WebElement
  """
  return WebDriverWait(
      driver,
      constants.ux.MAX_USER_WAIT_SECONDS) \
      .until(EC.presence_of_element_located(locator))


def get_when_all_visible(driver, locator):
  """Return WebElements by locator when all of them are visible.

  Args:
    driver (base.CustomDriver)
    locator (tuple)

  Returns:
      selenium.webdriver.remote.webelement.WebElements
  """
  return WebDriverWait(
      driver,
      constants.ux.MAX_USER_WAIT_SECONDS) \
      .until(EC.visibility_of_any_elements_located(locator))


def get_when_clickable(driver, locator):
  """
  Args:
    driver (base.CustomDriver)
    locator (tuple)

  Returns:
      selenium.webdriver.remote.webelement.WebElement
  """
  return WebDriverWait(
      driver,
      constants.ux.MAX_USER_WAIT_SECONDS) \
      .until(EC.element_to_be_clickable(locator))


def get_when_invisible(driver, locator):
  """
  Args:
    driver (base.CustomDriver)
    locator (tuple)

  Returns:
      selenium.webdriver.remote.webelement.WebElement
  """
  return WebDriverWait(
      driver,
      constants.ux.MAX_USER_WAIT_SECONDS) \
      .until(EC.invisibility_of_element_located(locator))


def wait_for_element_text(driver, locator, text):
  """
    Args:
      driver (base.CustomDriver)
      locator (tuple)
      text (str)
  """
  return WebDriverWait(
      driver,
      constants.ux.MAX_USER_WAIT_SECONDS) \
      .until(EC.text_to_be_present_in_element(locator, text))


def scroll_to_page_bottom(driver):
  """Scrolls to te page bottom using JS

  Args:
      driver (base.CustomDriver)
  """
  driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")


def is_value_in_attr(element, attr="class", value="active"):
  """Checks if the attribute value is present for given attribute

  Args:
    element (selenium.webdriver.remote.webelement.WebElement)
    attr (basestring): attribute name e.g. "class"
    value (basestring): value in the class attribute that
      indicates the element is now active/opened

  Returns:
      bool
  """
  attributes = element.get_attribute(attr)
  return value in attributes.split()


def wait_until_alert_is_present(driver):
  """
  Waits until an alert is present
  Args:
    driver (base.CustomDriver)

  Returns:
      selenium.webdriver.common.alert.Alert
  """
  return WebDriverWait(
      driver,
      constants.ux.MAX_ALERT_WAIT) \
      .until(EC.alert_is_present())


def handle_alert(driver, accept=False):
  """Wait until an alert is present and make a decision to accept or dismiss
  it"""
  try:
    wait_until_alert_is_present(driver)
    alert = driver.switch_to.alert

    if accept:
      alert.accept()
    else:
      alert.dismiss()
  except (exceptions.NoAlertPresentException, exceptions.TimeoutException):
    pass


def click_on_staleable_element(driver, el_locator):
  """Clicks an element that can be modified between the time we find it
  and when we click on it"""
  time_start = time.time()

  while time.time() - time_start < constants.ux.MAX_USER_WAIT_SECONDS:
    try:
      driver.find_element(*el_locator).click()
      break
    except exceptions.StaleElementReferenceException as err:
      logger.error(err)
      time.sleep(0.1)
  else:
    raise exception.ElementNotFound(el_locator)


def scroll_into_view(driver, element):
  """Scrolls page to element using JS"""
  driver.execute_script("return arguments[0].scrollIntoView();", element)

  # compensate for the header
  driver.execute_script(
      "window.scrollBy(0, -{});".format(constants.element.SIZE_HEADER))
  return element

@@ -154,20 +154,23 @@
 ort 
-time
+logging
 %0Aimport 
 logg
@@ -169,47 +169,104 @@
 ort 
-logging%0A%0A# pylint: disable=import-error
+time%0A%0Afrom selenium.common import exceptions%0Afrom selenium.webdriver.common import action_chains
 %0Afro
@@ -331,39 +331,8 @@
  EC%0A
-# pylint: disable=import-error%0A
 from
@@ -387,125 +387,8 @@
 ait%0A
-from selenium.webdriver.common import action_chains%0Afrom selenium.common import exceptions%0A%0Afrom lib import exception
 %0Afro
@@ -409,16 +409,42 @@
 onstants
+%0Afrom lib import exception
 %0A%0Alogger
@@ -1375,32 +1375,421 @@
 ted(locator))%0A%0A%0A
+def wait_until_condition(driver, condition):%0A  %22%22%22Wait until given expected condition is met%22%22%22%0A  WebDriverWait(%0A      driver,%0A      constants.ux.MAX_USER_WAIT_SECONDS).until(condition)%0A%0A%0Adef wait_until_not_present(driver, locator):%0A  %22%22%22Wait until no element(-s) for locator given are present in the DOM.%22%22%22%0A  wait_until_condition(driver, lambda d: len(d.find_elements(*locator)) == 0)%0A%0A%0A
 def get_when_all

Add method to wait when elements disappear