from bfs.bfs10135.errors import bfs10136
from copy import copy
from decorator import decorator
from errno import ESRCH as bfs10427, EACCES as bfs10426
from helium.bfs10146.bfs10150 import bfs10151
from helium.bfs10146.bfs10162 import bfs10167
from helium.bfs10135.errors import bfs10174
from helium.bfs10135.bfs10202 import bfs10223, bfs10224
from helium.bfs10365 import bfs10407, bfs10371, bfs10410
from helium.bfs10077.bfs10417 import bfs10422
from helium.bfs10077.bfs10424 import bfs10425
from helium.bfs10077.bfs10104 import bfs10154, bfs10157, bfs10155, bfs10163, bfs10156
from helium.bfs10077.bfs10140 import lower, predicate, bfs10147
from inspect import getargspec, ismethod, isfunction
from os import access, X_OK
from os.path import exists
from selenium.common.exceptions import UnexpectedAlertPresentException, ElementNotVisibleException, MoveTargetOutOfBoundsException, WebDriverException, StaleElementReferenceException, NoAlertPresentException
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support.ui import Select
from selenium.webdriver import Firefox, Chrome, Ie, DesiredCapabilities, ChromeOptions
from time import sleep, time
import atexit
import logging
import re
import collections
bfs10107 = logging.getLogger(__name__)
bfs10107.setLevel(logging.INFO)
@decorator
def bfs10434(bfs10400, self, *args, **bfs10430):
  if (self.driver.bfs10377() and AlertImpl(self.driver).exists()):
    return bfs10400(self, *args, **bfs10430)

  bfs10432 = self.driver.window_handles[:]
  bfs10431 = bfs10400(self, *args, **bfs10430)
  if (not (self.driver.bfs10377() and AlertImpl(self.driver).exists())):
    bfs10433 = [bfs10435 for bfs10435 in self.driver.window_handles if (bfs10435 not in bfs10432) ]
    if bfs10433:
      self.driver.switch_to.window(bfs10433[0])


  return bfs10431

@decorator
def bfs10440(bfs10400, *args, **bfs10436):
  try:
    return bfs10400(*args, **bfs10436)
  except UnexpectedAlertPresentException:
    raise UnexpectedAlertPresentException("This command is not supported when an alert is present. To accept the alert (this usually corresponds to clicking 'OK') use `Alert().accept()`. To dismiss the alert (ie. 'cancel' it), use `Alert().dismiss()`. If the alert contains a text field, you can use write(...) to set its value. Eg.: `write('hi there!')`.")


class APIImpl(object):
  def __init__(self, bfs10437, bfs10441, bfs10442=None):
    self.bfs10437 = bfs10437
    self.license = bfs10441
    self.bfs10442 = bfs10442
    self.driver = None

  def bfs10443(self, url=None):
    capabilities = DesiredCapabilities.FIREFOX.copy()
    capabilities['unexpectedAlertBehaviour'] = 'ignore'
    firefox = Firefox(capabilities=capabilities)
    return self._start(firefox, url)

  def bfs10451(self, url=None):
    bfs10444 = self.bfs10445()
    bfs10447 = ChromeOptions()
    bfs10447.add_argument('--test-type')
    bfs10446 = {'chrome_options': bfs10447}
    if exists(bfs10444):
      if (not access(bfs10444, X_OK)):
        try:
          bfs10425(bfs10444)
        except:
          raise RuntimeError(('The Chrome driver located at %s is not executable.' % bfs10444))


      bfs10107.info(('Using Chrome driver located at %s.' % bfs10444))
      bfs10446['executable_path'] = bfs10444
    else:
      bfs10107.warn(('Could not find Chrome driver at expected location %s.' % bfs10444))

    bfs10167()
    bfs10450 = Chrome(**bfs10446)
    atexit.register((lambda : self.bfs10452(bfs10450.service)))
    return self._start(bfs10450, url)

  def bfs10445(self):
    if bfs10154():
      bfs10453 = 'chromedriver.exe'
    elif bfs10157():
      bfs10453 = ('chromedriver' + ('_x64' if bfs10163() else '')
)
    else:
      assert bfs10155()
      bfs10453 = 'chromedriver'

    return self.bfs10437.bfs10063(bfs10156(), 'webdrivers', bfs10453)

  def bfs10452(self, service):
    if hasattr(service, 'process'):
      try:
        service.process.kill()
      except OSError as e:
        if (e.errno not in (bfs10427, bfs10426)):
          raise 




  def bfs10455(self, url=None):
    bfs10454 = self.bfs10437.bfs10063('win', 'webdrivers', 'IEDriverServer.exe')
    capabilities = DesiredCapabilities.INTERNETEXPLORER.copy()
    capabilities['ignoreZoomSetting'] = True
    bfs10446 = {'capabilities': capabilities}
    if exists(bfs10454):
      bfs10107.info(('Using IE driver located at %s.' % bfs10454))
      bfs10446['executable_path'] = bfs10454
    else:
      bfs10107.warn(('Could not find IE driver at expected location %s.' % bfs10454))

    bfs10456 = Ie(**bfs10446)
    atexit.register((lambda : self.bfs10452(bfs10456.iedriver)))
    return self._start(bfs10456, url)

  def _start(self, bfs10457, url=None):
    try:
      self.bfs10461(bfs10457)
    except bfs10136:
      bfs10457.quit()
      raise 

    if (url is not None):
      self.bfs10460(url)

    return self.bfs10462()

  @bfs10434
  @bfs10440
  def bfs10460(self, url):
    if ('://' not in url):
      url = ('http://' + url)

    self.driver.get(url)

  def bfs10461(self, driver):
    self.bfs10464(driver)
    self.driver = bfs10371(driver)

  def bfs10464(self, driver):
    try:
      self.license.bfs10463(bfs10223(self.bfs10442))
    except bfs10174:
      try:
        self.license.bfs10463(bfs10224(self.bfs10442, driver))
      except bfs10174:
        raise bfs10136('Unfortunately, Helium could not verify your license key. Please activate your internet connection and try again.')



  def bfs10462(self):
    if (self.driver is not None):
      return self.driver.unwrap()


  @bfs10434
  @bfs10440
  def bfs10470(self, text, into=None):
    if (into is not None):
      from helium.api import GUIElement
      if isinstance(into, GUIElement):
        into = into.bfs10465


    self.bfs10466(self.bfs10467, self.bfs10471, text, into=into)

  def bfs10467(self, text, into=None):
    if into:
      if isinstance(into, str):
        into = TextFieldImpl(self.driver, into)

      def _write(bfs10472):
        if (hasattr(bfs10472, 'clear') and isinstance(bfs10472.clear, collections.Callable)):
          bfs10472.clear()

        bfs10472.send_keys(text)

      self.bfs10473(into, _write)
    else:
      self.driver.switch_to.active_element.send_keys(text)


  def bfs10471(self, text, into=None):
    if (into is None):
      into = AlertImpl(self.driver)

    if (not isinstance(into, AlertImpl)):
      raise UnexpectedAlertPresentException(('into=%r is not allowed when an alert is present.' % into))

    into._write(text)

  def bfs10466(self, bfs10474, bfs10476, *args, **bfs10475):
    if (self.driver.bfs10375() or (not AlertImpl(self.driver).exists())):
      try:
        return bfs10474(*args, **bfs10475)
      except UnexpectedAlertPresentException:
        if (self.driver.bfs10375() and (not AlertImpl(self.driver).exists())):
          raise RuntimeError("An alert dialog was open but was closed by an expected exception. This normally happens when you called set_driver(...) with a Firefox driver you instantiated yourself without first setting selenium.webdriver.common.desired_capabilities.DesiredCapabilities.FIREFOX['unexpectedAlertBehaviour'] to 'ignore'. If this is not the case, please file a bug report at http://heliumhq.com.")



    return bfs10476(*args, **bfs10475)

  @bfs10434
  @bfs10440
  def bfs10477(self, key):
    self.driver.switch_to.active_element.send_keys(key)

  def bfs10502(self, element):
    element = self.bfs10500(element)
    click = (lambda bfs10501: bfs10501.click())
    self.bfs10503(element, click, click)

  def bfs10500(self, bfs10472):
    from helium.api import HTMLElement
    if isinstance(bfs10472, str):
      bfs10472 = bfs10504(self.driver, bfs10472)
    elif isinstance(bfs10472, HTMLElement):
      bfs10472 = bfs10472.bfs10465

    return bfs10472

  @bfs10434
  @bfs10440
  def bfs10503(self, element, bfs10506, bfs10505):
    offset = None
    from helium.api import Point
    if isinstance(element, Point):
      (element, offset) = self.bfs10507(element)

    if (offset is not None):
      bfs10373 = (lambda bfs10511: bfs10505(self.driver.bfs10373().move_to_element_with_offset(bfs10511, *offset)).perform())
    else:
      bfs10373 = (lambda bfs10510: bfs10506(bfs10510))

    self.bfs10473(element, bfs10373)

  def bfs10507(self, bfs10512):
    element = bfs10407(self.driver.execute_script(('return document.elementFromPoint(%r, %r);' % (bfs10512.x, bfs10512.y))))
    offset = (bfs10512 - (element.location.bfs10231, element.location.bfs10232))
    if ((offset == (0, 0)) and self.driver.bfs10375()):
      offset = (1, 1)

    return (element, offset)

  def bfs10514(self, element):
    element = self.bfs10500(element)
    self.bfs10503(element, (lambda bfs10513: self.driver.bfs10373().double_click(bfs10513).perform()), (lambda bfs10515: bfs10515.double_click()))

  def bfs10520(self, element, to):
    self.bfs10516(element)
    self.bfs10517(to)

  def bfs10516(self, element):
    element = self.bfs10500(element)
    self.bfs10503(element, (lambda bfs10521: self.driver.bfs10373().click_and_hold(bfs10521).perform()), (lambda bfs10523: bfs10523.click_and_hold()))

  def bfs10517(self, element):
    element = self.bfs10500(element)
    self.bfs10503(element, (lambda bfs10522: self.driver.bfs10373().move_to_element(bfs10522).release().perform()), (lambda bfs10524: bfs10524.release()))

  @bfs10440
  def bfs10526(self, predicate):
    return [predicate.bfs10525(bfs10527) for bfs10527 in predicate.bfs10465.find_all()]

  def bfs10531(self, num_pixels):
    self.bfs10530(0, num_pixels)

  def bfs10532(self, num_pixels):
    self.bfs10530(0, (-num_pixels))

  def bfs10534(self, num_pixels):
    self.bfs10530(num_pixels, 0)

  def bfs10533(self, num_pixels):
    self.bfs10530((-num_pixels), 0)

  @bfs10440
  def bfs10530(self, bfs10535, bfs10536):
    self.driver.execute_script('window.scrollBy(arguments[0], arguments[1]);', bfs10535, bfs10536)

  def bfs10541(self, element):
    element = self.bfs10500(element)
    self.bfs10503(element, (lambda bfs10540: self.driver.bfs10373().move_to_element(bfs10540).perform()), (lambda bfs10537: bfs10537))

  def bfs10544(self, element):
    element = self.bfs10500(element)
    self.bfs10503(element, (lambda bfs10543: self.driver.bfs10373().context_click(bfs10543).perform()), (lambda bfs10542: bfs10542.context_click()))

  @bfs10434
  @bfs10440
  def bfs10545(self, combo_box, value):
    from helium.api import ComboBox
    if isinstance(combo_box, str):
      combo_box = ComboBoxImpl(self.driver, combo_box)
    elif isinstance(combo_box, ComboBox):
      combo_box = combo_box.bfs10465

    def bfs10546(web_element):
      Select(web_element).select_by_visible_text(value)

    self.bfs10473(combo_box, bfs10546)

  def bfs10473(self, bfs10547, bfs10373):
    if (hasattr(bfs10547, 'perform') and isinstance(bfs10547.perform, collections.Callable)):
      self.driver.bfs10372 = bfs10547.perform(bfs10373)
    else:
      if isinstance(bfs10547, WebElement):
        bfs10547 = bfs10407(bfs10547)

      bfs10373(bfs10547)
      self.driver.bfs10372 = bfs10547


  @bfs10440
  def bfs10555(self, file_path, to):
    to = self.bfs10500(to)
    drag_and_drop = bfs10550(self.driver, file_path)
    drag_and_drop.begin()
    try:
      drag_and_drop.bfs10551()
      self.bfs10473(to, (lambda bfs10552: drag_and_drop.bfs10553(bfs10552)))
    finally:
      drag_and_drop.end()


  def bfs10557(self, file_path, to=None):
    if (to is None):
      to = bfs10554(self.driver)
    elif isinstance(to, str):
      to = bfs10554(self.driver, to)

    bfs10556 = (lambda bfs10560: bfs10560.send_keys(file_path))
    self.bfs10503(to, bfs10556, bfs10556)

  def bfs10563(self):
    self.bfs10466(self.bfs10561, self.bfs10562)

  def bfs10561(self):
    self.driver.refresh()

  def bfs10562(self):
    AlertImpl(self.driver).accept()
    self.bfs10561()

  def bfs10571(self, condition_fn, timeout_secs=10, interval_secs=0.5):
    if ismethod(condition_fn):
      bfs10565 = (condition_fn.__self__ is not None)
      bfs10564 = getargspec(condition_fn).args
      bfs10566 = (len(bfs10564) - (1 if bfs10565 else 0)
)
    else:
      if (not isfunction(condition_fn)):
        condition_fn = condition_fn.__call__

      bfs10564 = getargspec(condition_fn).args
      bfs10566 = len(bfs10564)

    bfs10567 = (condition_fn if bfs10566 else (lambda driver: condition_fn()))

    wait = WebDriverWait(self.bfs10462(), timeout_secs, poll_frequency=interval_secs)
    wait.until(bfs10567)

  @bfs10440
  def bfs10570(self, window):
    from helium.api import Window
    if isinstance(window, str):
      window = WindowImpl(self.driver, window)
    elif isinstance(window, Window):
      window = window.bfs10465

    self.driver.switch_to.window(window.handle)

  def bfs10572(self):
    self.driver.quit()

  @bfs10440
  def bfs10574(self, element):
    from helium.api import HTMLElement
    if isinstance(element, HTMLElement):
      element = element.bfs10465

    if hasattr(element, 'first_occurrence'):
      element = element.first_occurrence

    if isinstance(element, bfs10407):
      element = element.unwrap()

    bfs10573 = element.get_attribute('style')
    self.driver.execute_script("arguments[0].setAttribute('style', 'border: 2px solid red; font-weight: bold;');", element)
    self.driver.execute_script("var target = arguments[0];var previousStyle = arguments[1];setTimeout(function() {target.setAttribute('style', previousStyle);}, 2000);", element, bfs10573)


class bfs10550(object):
  def __init__(self, driver, file_path):
    self.driver = driver
    self.file_path = file_path
    self.bfs10576 = None
    self.bfs10575 = None

  def begin(self):
    self.bfs10577()
    try:
      self.bfs10576.send_keys(self.file_path)
    except:
      self.end()
      raise 


  def bfs10577(self):
    self.bfs10576 = self.driver.execute_script("var input = document.createElement('input');input.type = 'file';input.style.display = 'block';input.style.opacity = '1';input.style.visibility = 'visible';input.style.height = '1px';input.style.width = '1px';if (document.body.childElementCount > 0) {   document.body.insertBefore(input, document.body.childNodes[0]);} else {   document.body.appendChild(input);}return input;")

  def bfs10551(self):
    self.bfs10600('dragenter', to='document.body')
    self.bfs10575 = self.bfs10601('dragover', 'document', interval_msecs=300)
    self.bfs10575.start()

  def bfs10600(self, bfs10602, to):
    (bfs10603, args) = self.bfs10605(bfs10602, to)
    self.driver.execute_script(bfs10603, *args)

  def bfs10601(self, bfs10604, to, interval_msecs):
    (bfs10606, args) = self.bfs10605(bfs10604, to)
    return bfs10610(self.driver, bfs10606, args, interval_msecs)

  def bfs10605(self, bfs10607, to):
    bfs10611 = "var files = arguments[0].files;var items = [];var types = [];for (var i = 0; i < files.length; i++) {   items[i] = {kind: 'file', type: files[i].type};   types[i] = 'Files';}var event = document.createEvent('CustomEvent');event.initCustomEvent(arguments[1], true, true, 0);event.dataTransfer = {\tfiles: files,\titems: items,\ttypes: types};arguments[2].dispatchEvent(event);"
    if isinstance(to, str):
      bfs10611 = bfs10611.replace('arguments[2]', to)
      args = (self.bfs10576, bfs10607)
    else:
      args = (self.bfs10576, bfs10607, to.unwrap())

    return (bfs10611, args)

  def bfs10553(self, target):
    self.bfs10575.stop()
    self.bfs10600('drop', to=target)

  def end(self):
    if (self.bfs10576 is not None):
      self.driver.execute_script('arguments[0].parentNode.removeChild(arguments[0]);', self.bfs10576)

    self.bfs10576 = None


class bfs10610(object):
  def __init__(self, driver, bfs10612, args, interval_msecs):
    self.driver = driver
    self.bfs10612 = bfs10612
    self.args = args
    self.interval_msecs = interval_msecs
    self.bfs10613 = None

  def start(self):
    bfs10615 = ('var originalArguments = arguments;return setInterval(function() {\targuments = originalArguments;\t%s}, %d);' % (self.bfs10612, self.interval_msecs))
    self.bfs10613 = self.driver.execute_script(bfs10615, *self.args)

  def stop(self):
    self.driver.execute_script('clearInterval(arguments[0]);', self.bfs10613)
    self.bfs10613 = None


class bfs10614(object):
  def __init__(self, driver):
    self.bfs10616 = None
    self.bfs10617 = driver

  def find_all(self):
    if self.bfs10621():
      yield self
    else:
      for bfs10620 in self.bfs10622():
        yield self.bfs10624(bfs10620)



  def bfs10621(self):
    return (self.bfs10616 is not None)

  def bfs10622(self):
    raise NotImplementedError()

  def bfs10624(self, bfs10623):
    bfs10625 = copy(self)
    bfs10625.bfs10616 = bfs10623
    return bfs10625

  def exists(self):
    try:
      next(self.find_all())
    except StopIteration:
      return False
    else:
      return True


  @property
  def first_occurrence(self):
    if (not self.bfs10621()):
      self.bfs10626()

    return self.bfs10616

  def bfs10626(self):
    self.perform((lambda bfs10627: None))

  def perform(self, bfs10373):
    from helium.api import Config
    bfs10631 = (time() + Config.implicit_wait_secs)
    bfs10630 = self.bfs10632(bfs10373)
    while ((bfs10630 is None) and (time() < bfs10631)):
      bfs10630 = self.bfs10632(bfs10373)

    if (bfs10630 is not None):
      return bfs10630

    raise LookupError()

  def bfs10632(self, bfs10373):
    for bfs10633 in self.find_all():
      bfs10635 = bfs10633.first_occurrence
      try:
        bfs10373(bfs10635)
      except Exception as e:
        if self.bfs10634(e):
          continue
        else:
          raise 

      else:
        self.bfs10616 = bfs10635
        return bfs10635



  def bfs10634(self, exception):
    if isinstance(exception, ElementNotVisibleException):
      return True

    if isinstance(exception, MoveTargetOutOfBoundsException):
      return True

    if isinstance(exception, WebDriverException):
      msg = exception.msg
      if (('Element is not clickable at point' in msg) and ('Other element would receive the click' in msg)):
        bfs10107.info('Ignoring exception %r while trying to click element. It could be that the element has moved.', msg, exc_info=True)
        return True


    return False


class bfs10636(bfs10614):
  def __init__(self, driver, below=None, to_right_of=None, above=None, to_left_of=None):
    super(bfs10636, self).__init__(driver)
    self.below = self.bfs10637(below)
    self.to_right_of = self.bfs10637(to_right_of)
    self.above = self.bfs10637(above)
    self.to_left_of = self.bfs10637(to_left_of)
    self.bfs10641 = bfs10151()

  def bfs10637(self, element):
    if isinstance(element, str):
      return TextImpl(self.bfs10617, element)

    from helium.api import HTMLElement
    if isinstance(element, HTMLElement):
      return element.bfs10465

    return element

  @property
  def width(self):
    return self.first_occurrence.location.width

  @property
  def height(self):
    return self.first_occurrence.location.height

  @property
  def x(self):
    return self.first_occurrence.location.bfs10231

  @property
  def y(self):
    return self.first_occurrence.location.bfs10232

  @property
  def top_left(self):
    from helium.api import Point
    return Point(self.x, self.y)

  @property
  def web_element(self):
    return self.first_occurrence.unwrap()

  def bfs10622(self):
    bfs10640 = self.bfs10642()
    for bfs10643 in bfs10410(self.bfs10617):
      for bfs10645 in self.bfs10644():
        if self.bfs10646(bfs10645, bfs10640):
          yield bfs10645




  def bfs10642(self):
    bfs10630 = []
    if self.below:
      bfs10630.append(list(map((lambda bfs10647: bfs10647.location.is_above), self.below.bfs10622())))

    if self.to_right_of:
      bfs10630.append(list(map((lambda bfs10650: bfs10650.location.is_to_left_of), self.to_right_of.bfs10622())))

    if self.above:
      bfs10630.append(list(map((lambda bfs10651: bfs10651.location.is_below), self.above.bfs10622())))

    if self.to_left_of:
      bfs10630.append(list(map((lambda bfs10653: bfs10653.location.is_to_right_of), self.to_left_of.bfs10622())))

    return bfs10630

  def bfs10646(self, bfs10652, bfs10654):
    return (bfs10652.is_displayed() and self.bfs10656(bfs10652, bfs10654))

  def bfs10656(self, element, bfs10655):
    for bfs10657 in bfs10655:
      bfs10660 = False
      for bfs10661 in bfs10657:
        if bfs10661(element.location):
          bfs10660 = True
          break


      if (not bfs10660):
        return False


    return True

  def bfs10644(self):
    raise NotImplementedError()

  def bfs10662(self):
    return (self.first_occurrence.get_attribute('disabled') is None)


class SImpl(bfs10636):
  def __init__(self, driver, bfs10663):
    super(bfs10636, self).__init__(driver)
    self.bfs10663 = bfs10663

  def bfs10644(self):
    wrap = (lambda bfs10665: list(map(bfs10407, bfs10665)))
    if self.bfs10663.startswith('@'):
      return wrap(self.bfs10617.find_elements_by_name(self.bfs10663[1:]))

    if self.bfs10663.startswith('//'):
      return wrap(self.bfs10617.find_elements_by_xpath(self.bfs10663))

    return wrap(self.bfs10617.find_elements_by_css_selector(self.bfs10663))

  def bfs10642(self):
    return []


class bfs10664(bfs10636):
  def bfs10644(self):
    bfs10666 = self.bfs10670()
    bfs10107.debug(('Looking for HTML element using xpath: %s.' % bfs10666))
    return self.bfs10667(list(map(bfs10407, self.bfs10617.find_elements_by_xpath(bfs10666))))

  def bfs10667(self, bfs10671):
    bfs10672 = []
    for bfs10674 in bfs10671:
      try:
        key = self.bfs10673(bfs10674)
      except StaleElementReferenceException:
        pass
      else:
        bfs10672.append((key, bfs10674))


    bfs10675 = (lambda bfs10677: bfs10677[0])
    bfs10672.sort(key=bfs10675)
    bfs10676 = (lambda bfs10700: bfs10700[1])
    return list(map(bfs10676, bfs10672))

  def bfs10670(self):
    raise NotImplementedError()

  def bfs10673(self, web_element):
    return (self.bfs10617.bfs10376(web_element) + 1)


class bfs10702(bfs10664):
  def __init__(self, driver, text=None, **bfs10701):
    super(bfs10702, self).__init__(driver, **bfs10701)
    self.search_text = text

  def bfs10670(self):
    bfs10703 = (('//' + self.bfs10705()) + predicate(self.bfs10641.bfs10140('.', self.search_text)))
    return ('%s[not(self::script)][not(.%s)]' % (bfs10703, bfs10703))

  def bfs10705(self):
    return '*'


class TextImpl(bfs10702):
  def __init__(self, driver, text=None, include_free_text=True, **bfs10704):
    super(TextImpl, self).__init__(driver, text, **bfs10704)
    self.include_free_text = include_free_text

  @property
  def value(self):
    return self.first_occurrence.text

  def bfs10670(self):
    bfs10706 = [(super(TextImpl, self).bfs10670() + '[not(self::option)]'), ButtonImpl(self.bfs10617, self.search_text).bfs10707(), LinkImpl(self.bfs10617, self.search_text).bfs10670()]
    if self.include_free_text:
      bfs10706.append(bfs10711(self.bfs10617, self.search_text).bfs10670())

    return ' | '.join(bfs10706)


class bfs10711(bfs10702):
  def bfs10705(self):
    return 'text()'

  def bfs10670(self):
    return (super(bfs10711, self).bfs10670() + '/..')


class LinkImpl(bfs10702):
  def bfs10705(self):
    return 'a'

  def bfs10670(self):
    return ((((((super(LinkImpl, self).bfs10670() + ' | ') + '//a') + predicate(self.bfs10641.bfs10140('@title', self.search_text))) + ' | ') + "//*[@role='link']") + predicate(self.bfs10641.bfs10140('.', self.search_text)))


class ListItemImpl(bfs10702):
  def bfs10705(self):
    return 'li'


class ButtonImpl(bfs10702):
  def bfs10705(self):
    return 'button'

  def is_enabled(self):
    bfs10710 = self.first_occurrence.get_attribute('aria-disabled')
    return (self.bfs10662() and ((not bfs10710) or (bfs10710.lower() == 'false')))

  def bfs10670(self):
    bfs10712 = self.bfs10641.bfs10140('@aria-label', self.search_text)
    bfs10714 = self.bfs10641.bfs10140('.', self.search_text)
    bfs10713 = bfs10147(bfs10712, bfs10714)
    return ' | '.join([super(ButtonImpl, self).bfs10670(), self.bfs10707(), ("//*[@role='button']" + bfs10713), ('//button' + predicate(bfs10712))])

  def bfs10707(self):
    if self.search_text:
      bfs10715 = self.bfs10641.bfs10140('@value', self.search_text)
      bfs10717 = self.bfs10641.bfs10140('@label', self.search_text)
      bfs10716 = self.bfs10641.bfs10140('@aria-label', self.search_text)
      bfs10720 = self.bfs10641.bfs10140('@title', self.search_text)
      bfs10722 = bfs10147(bfs10715, bfs10717, bfs10716, bfs10720)
    else:
      bfs10722 = ''

    return ("//input[@type='submit' or @type='button']" + bfs10722)


class ImageImpl(bfs10664):
  def __init__(self, driver, alt, **bfs10721):
    super(ImageImpl, self).__init__(driver, **bfs10721)
    self.alt = alt

  def bfs10670(self):
    return ('//img' + predicate(self.bfs10641.bfs10140('@alt', self.alt)))


class bfs10723(bfs10636):
  bfs10724 = 1.5
  def __init__(self, driver, label=None, **bfs10725):
    super(bfs10723, self).__init__(driver, **bfs10725)
    self.label = label

  def bfs10644(self):
    if (not self.label):
      bfs10727 = self.bfs10726()
    else:
      bfs10730 = TextImpl(self.bfs10617, self.label, include_free_text=False).bfs10644()
      if bfs10730:
        bfs10727 = list(self.bfs10731(self.bfs10726(), bfs10730))
      else:
        bfs10727 = self.bfs10733()


    return sorted(bfs10727, key=self.bfs10617.bfs10376)

  def bfs10726(self, bfs10732=None):
    if (bfs10732 is None):
      bfs10732 = self.bfs10670()

    return list(map(bfs10407, self.bfs10617.find_elements_by_xpath(bfs10732)))

  def bfs10733(self):
    bfs10734 = [bfs10140.strip().lstrip('/') for bfs10140 in self.bfs10670().split('|')]
    bfs10735 = ('//text()' + predicate(self.bfs10641.bfs10140('.', self.label)))
    bfs10140 = ' | '.join([(((bfs10735 + '/following::') + bfs10736) + '[1]') for bfs10736 in bfs10734])
    return self.bfs10726(bfs10140)

  def bfs10670(self):
    raise NotImplementedError()

  def bfs10740(self):
    return 'to_right_of'

  def bfs10737(self):
    return 'below'

  def bfs10731(self, bfs10741, bfs10742):
    for (label, bfs10744) in self.bfs10743(bfs10741, bfs10742):
      yield bfs10744
      bfs10742.remove(label)
      bfs10741.remove(bfs10744)

    bfs10745 = self.bfs10746(bfs10741, bfs10742)
    bfs10745 = self.bfs10750(bfs10745)
    self.bfs10747(bfs10745)
    for bfs10751 in list(bfs10745.values()):
      assert (len(bfs10751) <= 1)
      if bfs10751:
        yield next(iter(bfs10751))



  def bfs10743(self, bfs10752, bfs10754):
    for label in bfs10754:
      if (label.tag_name == 'label'):
        bfs10753 = label.get_attribute('for')
        if bfs10753:
          for bfs10755 in bfs10752:
            bfs10756 = bfs10755.get_attribute('id')
            if (bfs10756.lower() == bfs10753.lower()):
              yield (label, bfs10755)






  def bfs10746(self, bfs10757, bfs10760):
    bfs10762 = {}
    for label in bfs10760:
      for bfs10761 in bfs10757:
        if self.bfs10763(bfs10761, label):
          if (label not in bfs10762):
            bfs10762[label] = set()

          bfs10762[label].add(bfs10761)



    return bfs10762

  def bfs10763(self, bfs10765, label):
    if bfs10765.location.bfs10274(label.location):
      return True

    bfs10764 = self.bfs10740()
    bfs10766 = self.bfs10737()
    return ((label.location.bfs10323(bfs10765.location) <= 150) and (bfs10765.location.bfs10312(bfs10764, label.location) or bfs10765.location.bfs10312(bfs10766, label.location)))

  def bfs10750(self, bfs10770):
    bfs10767 = bfs10422(bfs10770)
    self.bfs10747(bfs10767)
    return bfs10422(bfs10767)

  def bfs10747(self, bfs10771):
    for (bfs10772, bfs10773) in list(bfs10771.items()):
      if bfs10773:
        bfs10771[bfs10772] = set([self.bfs10775(bfs10772, bfs10773)])



  def bfs10775(self, bfs10774, bfs10776):
    bfs11000 = iter(bfs10776)
    bfs10777 = next(bfs11000)
    bfs11001 = self.bfs11002(bfs10777, bfs10774)
    for element in bfs11000:
      bfs11004 = self.bfs11002(element, bfs10774)
      if (bfs11004 < bfs11001):
        bfs10777 = element
        bfs11001 = bfs11004


    return bfs10777

  def bfs11002(self, bfs11003, bfs11005):
    bfs11007 = bfs11003.location
    bfs11006 = bfs11005.location
    if bfs11007.bfs10312(self.bfs10737(), bfs11006):
      bfs11010 = self.bfs10724
    else:
      bfs11010 = 1

    return (bfs11010 * bfs11007.bfs10323(bfs11006))


class bfs11012(bfs10636):
  def __init__(self, driver, *args, **bfs10446):
    super(bfs11012, self).__init__(driver, **bfs10446)
    self.args = ([driver] + list(args))
    self.bfs10446 = bfs10446
    self.bfs11011 = None

  @property
  def bfs11013(self):
    if (self.bfs11011 is None):
      self.bfs10626()

    return self.bfs11011

  def find_all(self):
    bfs11014 = []
    for element in self.bfs11015():
      for bfs11016 in element.find_all():
        if (self.bfs11011 is None):
          self.bfs11011 = element

        if (bfs11016 not in bfs11014):
          yield bfs11016
          bfs11014.append(bfs11016)




  def bfs11015(self):
    for bfs11020 in self.bfs11017():
      yield bfs11020(*self.args, **self.bfs10446)


  def bfs11017(self):
    raise NotImplementedError()


class bfs10504(bfs11012):
  def __init__(self, driver, text, **bfs11021):
    super(bfs10504, self).__init__(driver, text, **bfs11021)

  def bfs11017(self):
    return [ButtonImpl, TextImpl, ImageImpl]


class TextFieldImpl(bfs11012):
  def __init__(self, driver, label=None, **bfs11023):
    super(TextFieldImpl, self).__init__(driver, label, **bfs11023)

  def bfs11017(self):
    return [bfs11022, bfs11024, bfs11025]

  @property
  def value(self):
    return self.bfs11013.value

  def is_enabled(self):
    return self.bfs11013.is_enabled()

  def is_editable(self):
    return self.bfs11013.is_editable()


class bfs11024(bfs10723):
  @property
  def value(self):
    return (self.first_occurrence.get_attribute('value') or '')

  def is_enabled(self):
    return self.bfs10662()

  def is_editable(self):
    return (self.first_occurrence.get_attribute('readOnly') is None)

  def bfs10670(self):
    return (("//input[%s='text' or %s='email' or %s='password' or %s='number' or %s='tel' or string-length(@type)=0]" % ((lower('@type'),) * 5)) + " | //textarea | //*[@contenteditable='true']")


class bfs11025(bfs10723):
  @property
  def value(self):
    return self.first_occurrence.text

  def is_enabled(self):
    return self.bfs10662()

  def is_editable(self):
    return (self.first_occurrence.get_attribute('readOnly') is None)

  def bfs10670(self):
    return "//*[@role='textbox']"


class bfs11022(bfs10664):
  def __init__(self, driver, label, **bfs11026):
    super(bfs11022, self).__init__(driver, **bfs11026)
    self.label = label

  @property
  def value(self):
    return (self.first_occurrence.get_attribute('value') or '')

  def is_enabled(self):
    return self.bfs10662()

  def is_editable(self):
    return (self.first_occurrence.get_attribute('readOnly') is None)

  def bfs10670(self):
    return ('(%s)%s' % (bfs11024(self.label).bfs10670(), predicate(self.bfs10641.bfs10140('@placeholder', self.label))))


class bfs10554(bfs10723):
  def bfs10670(self):
    return "//input[@type='file']"


class ComboBoxImpl(bfs11012):
  def __init__(self, driver, label=None, **bfs11027):
    super(ComboBoxImpl, self).__init__(driver, label, **bfs11027)

  def bfs11017(self):
    return [bfs11031, bfs11030]

  def is_editable(self):
    return (self.first_occurrence.tag_name != 'select')

  @property
  def value(self):
    bfs11032 = self.bfs11033.first_selected_option
    if bfs11032:
      return bfs11032.text

    return None

  @property
  def options(self):
    return [bfs11034.text for bfs11034 in self.bfs11033.options]

  @property
  def bfs11033(self):
    return Select(self.web_element)


class bfs11031(bfs10723):
  def bfs10670(self):
    return '//select | //input[@list]'


class bfs11030(bfs10702):
  def bfs10705(self):
    return 'option'

  def bfs10670(self):
    bfs11036 = super(bfs11030, self).bfs10670()
    return (bfs11036 + '/ancestor::select[1]')

  def bfs10644(self):
    bfs11035 = super(bfs11030, self).bfs10644()
    bfs11037 = []
    for bfs11040 in bfs11035:
      for bfs11042 in Select(bfs11040.unwrap()).all_selected_options:
        if self.bfs10641.text(bfs11042.text, self.search_text):
          bfs11037.append(bfs11040)
          break



    return bfs11037


class CheckBoxImpl(bfs10723):
  def is_enabled(self):
    return self.bfs10662()

  def is_checked(self):
    return (self.first_occurrence.get_attribute('checked') is not None)

  def bfs10670(self):
    return "//input[@type='checkbox']"

  def bfs10740(self):
    return 'to_left_of'

  def bfs10737(self):
    return 'to_right_of'


class RadioButtonImpl(bfs10723):
  def is_selected(self):
    return (self.first_occurrence.get_attribute('checked') is not None)

  def bfs10670(self):
    return "//input[@type='radio']"

  def bfs10740(self):
    return 'to_left_of'

  def bfs10737(self):
    return 'to_right_of'


class WindowImpl(bfs10614):
  def __init__(self, driver, title=None):
    super(WindowImpl, self).__init__(driver)
    self.bfs11041 = title

  def bfs10622(self):
    bfs11043 = []
    for handle in self.bfs10617.window_handles:
      window = WindowImpl.bfs11044(self.bfs10617, handle)
      if (self.bfs11041 is None):
        bfs11043.append((0, window))
      else:
        title = window.title
        if title.startswith(self.bfs11041):
          bfs11045 = (len(title) - len(self.bfs11041))
          bfs11043.append((bfs11045, window))



    bfs11045 = (lambda bfs11047: bfs11047[0])
    bfs11043.sort(key=bfs11045)
    for (bfs11045, window) in bfs11043:
      yield window


  @property
  def title(self):
    return self.first_occurrence.title

  @property
  def handle(self):
    return self.first_occurrence.handle

  class bfs11044(object):
    def __init__(self, driver, handle):
      self.driver = driver
      self.handle = handle
      self.bfs11046 = None

    @property
    def title(self):
      with self:
        return self.driver.title


    def __enter__(self):
      self.bfs11046 = self.driver.current_window_handle
      if (self.driver.current_window_handle != self.handle):
        self.driver.switch_to.window(self.handle)


    def __exit__(self, *bfs11050):
      if (self.driver.current_window_handle != self.bfs11046):
        self.driver.switch_to.window(self.bfs11046)




class AlertImpl(bfs10614):
  def __init__(self, driver, search_text=None):
    super(AlertImpl, self).__init__(driver)
    self.search_text = search_text

  def bfs10622(self):
    bfs11051 = self.bfs10617.switch_to.alert
    try:
      text = bfs11051.text
      if ((self.search_text is None) or text.startswith(self.search_text)):
        yield bfs11051

    except NoAlertPresentException:
      pass


  @property
  def text(self):
    return self.first_occurrence.text

  def accept(self):
    first_occurrence = self.first_occurrence
    try:
      first_occurrence.accept()
    except WebDriverException as e:
      msg = e.msg
      if (msg and re.match('a\\.document\\.getElementsByTagName\\([^\\)]*\\)\\[0\\] is undefined', msg)):
        bfs10107.warn('Got %r when trying to accept alert. Trying again after 0.25s.', e)
        sleep(0.25)
        first_occurrence.accept()
      else:
        raise 



  def dismiss(self):
    self.first_occurrence.dismiss()

  def _write(self, text):
    self.first_occurrence.send_keys(text)


