from bfs.bfs10131.errors import bfs10135
from copy import copy
from decorator import decorator
from errno import ESRCH as bfs10433, EACCES as bfs10435
from helium.bfs10145.bfs10147 import bfs10150
from helium.bfs10145.bfs10161 import bfs10166
from helium.bfs10131.errors import bfs10171
from helium.bfs10131.bfs10177 import bfs10227, bfs10232
from helium.bfs10372 import bfs10415, bfs10375, bfs10416
from helium.bfs10076.bfs10425 import bfs10430
from helium.bfs10076.bfs10432 import bfs10431
from helium.bfs10076.system import bfs10151, bfs10154, bfs10153, bfs10160, bfs10155
from helium.bfs10076.bfs10137 import lower, predicate, bfs10143
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
bfs10106 = logging.getLogger(__name__)
bfs10106.setLevel(logging.INFO)
@decorator
def bfs10442(bfs10405, self, *args, **bfs10434):
  if (self.driver.bfs10403() and AlertImpl(self.driver).exists()):
    return bfs10405(self, *args, **bfs10434)

  bfs10436 = self.driver.window_handles[:]
  bfs10440 = bfs10405(self, *args, **bfs10434)
  if (not (self.driver.bfs10403() and AlertImpl(self.driver).exists())):
    bfs10437 = [bfs10441 for bfs10441 in self.driver.window_handles if (bfs10441 not in bfs10436) ]
    if bfs10437:
      self.driver.switch_to.window(bfs10437[0])


  return bfs10440

@decorator
def bfs10444(bfs10405, *args, **bfs10443):
  try:
    return bfs10405(*args, **bfs10443)
  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, bfs10445, bfs10447, bfs10446=None):
    self.bfs10445 = bfs10445
    self.license = bfs10447
    self.bfs10446 = bfs10446
    self.driver = None

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

  def bfs10457(self, url=None):
    bfs10452 = self.bfs10451()
    bfs10453 = ChromeOptions()
    bfs10453.add_argument('--test-type')
    bfs10454 = {'chrome_options': bfs10453}
    if exists(bfs10452):
      if (not access(bfs10452, X_OK)):
        try:
          bfs10431(bfs10452)
        except:
          raise RuntimeError(('The Chrome driver located at %s is not executable.' % bfs10452))


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

    bfs10166()
    bfs10456 = Chrome(**bfs10454)
    atexit.register((lambda : self.bfs10455(bfs10456.service)))
    return self._start(bfs10456, url)

  def bfs10451(self):
    if bfs10151():
      bfs10461 = 'chromedriver.exe'
    elif bfs10154():
      bfs10461 = ('chromedriver' + ('_x64' if bfs10160() else '')
)
    else:
      assert bfs10153()
      bfs10461 = 'chromedriver'

    return self.bfs10445.bfs10062(bfs10155(), 'webdrivers', bfs10461)

  def bfs10455(self, service):
    if hasattr(service, 'process'):
      try:
        service.process.kill()
      except OSError as e:
        if (e.errno not in (bfs10433, bfs10435)):
          raise 




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

    bfs10462 = Ie(**bfs10454)
    atexit.register((lambda : self.bfs10455(bfs10462.iedriver)))
    return self._start(bfs10462, url)

  def _start(self, bfs10463, url=None):
    try:
      self.bfs10465(bfs10463)
    except bfs10135:
      bfs10463.quit()
      raise 

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

    return self.bfs10467()

  @bfs10442
  @bfs10444
  def bfs10466(self, url):
    if ('://' not in url):
      url = ('http://' + url)

    self.driver.get(url)

  def bfs10465(self, driver):
    self.bfs10471(driver)
    self.driver = bfs10375(driver)

  def bfs10471(self, driver):
    try:
      self.license.bfs10470(bfs10227(self.bfs10446))
    except bfs10171:
      try:
        self.license.bfs10470(bfs10232(self.bfs10446, driver))
      except bfs10171:
        raise bfs10135('Unfortunately, Helium could not verify your license key. Please activate your internet connection and try again.')



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


  @bfs10442
  @bfs10444
  def bfs10475(self, text, into=None):
    if (into is not None):
      from helium.api import GUIElement
      if isinstance(into, GUIElement):
        into = into.bfs10472


    self.bfs10473(self.bfs10474, self.bfs10476, text, into=into)

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

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

        bfs10477.send_keys(text)

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


  def bfs10476(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 bfs10473(self, bfs10501, bfs10503, *args, **bfs10502):
    if (self.driver.bfs10404() or (not AlertImpl(self.driver).exists())):
      try:
        return bfs10501(*args, **bfs10502)
      except UnexpectedAlertPresentException:
        if (self.driver.bfs10404() 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 bfs10503(*args, **bfs10502)

  @bfs10442
  @bfs10444
  def bfs10504(self, key):
    self.driver.switch_to.active_element.send_keys(key)

  def bfs10511(self, element):
    element = self.bfs10506(element)
    click = (lambda bfs10505: bfs10505.click())
    self.bfs10507(element, click, click)

  def bfs10506(self, bfs10477):
    from helium.api import HTMLElement
    if isinstance(bfs10477, str):
      bfs10477 = bfs10510(self.driver, bfs10477)
    elif isinstance(bfs10477, HTMLElement):
      bfs10477 = bfs10477.bfs10472

    return bfs10477

  @bfs10442
  @bfs10444
  def bfs10507(self, element, bfs10512, bfs10513):
    offset = None
    from helium.api import Point
    if isinstance(element, Point):
      (element, offset) = self.bfs10515(element)

    if (offset is not None):
      bfs10400 = (lambda bfs10514: bfs10513(self.driver.bfs10400().move_to_element_with_offset(bfs10514, *offset)).perform())
    else:
      bfs10400 = (lambda bfs10516: bfs10512(bfs10516))

    self.bfs10500(element, bfs10400)

  def bfs10515(self, bfs10517):
    element = bfs10415(self.driver.execute_script(('return document.elementFromPoint(%r, %r);' % (bfs10517.x, bfs10517.y))))
    offset = (bfs10517 - (element.location.bfs10237, element.location.bfs10236))
    if ((offset == (0, 0)) and self.driver.bfs10404()):
      offset = (1, 1)

    return (element, offset)

  def bfs10523(self, element):
    element = self.bfs10506(element)
    self.bfs10507(element, (lambda bfs10520: self.driver.bfs10400().double_click(bfs10520).perform()), (lambda bfs10521: bfs10521.double_click()))

  def bfs10525(self, element, to):
    self.bfs10522(element)
    self.bfs10524(to)

  def bfs10522(self, element):
    element = self.bfs10506(element)
    self.bfs10507(element, (lambda bfs10527: self.driver.bfs10400().click_and_hold(bfs10527).perform()), (lambda bfs10526: bfs10526.click_and_hold()))

  def bfs10524(self, element):
    element = self.bfs10506(element)
    self.bfs10507(element, (lambda bfs10530: self.driver.bfs10400().move_to_element(bfs10530).release().perform()), (lambda bfs10531: bfs10531.release()))

  @bfs10444
  def bfs10533(self, predicate):
    return [predicate.bfs10532(bfs10534) for bfs10534 in predicate.bfs10472.find_all()]

  def bfs10536(self, num_pixels):
    self.bfs10535(0, num_pixels)

  def bfs10540(self, num_pixels):
    self.bfs10535(0, (-num_pixels))

  def bfs10537(self, num_pixels):
    self.bfs10535(num_pixels, 0)

  def bfs10541(self, num_pixels):
    self.bfs10535((-num_pixels), 0)

  @bfs10444
  def bfs10535(self, bfs10543, bfs10542):
    self.driver.execute_script('window.scrollBy(arguments[0], arguments[1]);', bfs10543, bfs10542)

  def bfs10545(self, element):
    element = self.bfs10506(element)
    self.bfs10507(element, (lambda bfs10544: self.driver.bfs10400().move_to_element(bfs10544).perform()), (lambda bfs10546: bfs10546))

  def bfs10551(self, element):
    element = self.bfs10506(element)
    self.bfs10507(element, (lambda bfs10547: self.driver.bfs10400().context_click(bfs10547).perform()), (lambda bfs10550: bfs10550.context_click()))

  @bfs10442
  @bfs10444
  def bfs10553(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.bfs10472

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

    self.bfs10500(combo_box, bfs10552)

  def bfs10500(self, bfs10555, bfs10400):
    if (hasattr(bfs10555, 'perform') and isinstance(bfs10555.perform, collections.Callable)):
      self.driver.bfs10377 = bfs10555.perform(bfs10400)
    else:
      if isinstance(bfs10555, WebElement):
        bfs10555 = bfs10415(bfs10555)

      bfs10400(bfs10555)
      self.driver.bfs10377 = bfs10555


  @bfs10444
  def bfs10561(self, file_path, to):
    to = self.bfs10506(to)
    drag_and_drop = bfs10554(self.driver, file_path)
    drag_and_drop.begin()
    try:
      drag_and_drop.bfs10556()
      self.bfs10500(to, (lambda bfs10560: drag_and_drop.bfs10557(bfs10560)))
    finally:
      drag_and_drop.end()


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

    bfs10563 = (lambda bfs10565: bfs10565.send_keys(file_path))
    self.bfs10507(to, bfs10563, bfs10563)

  def bfs10571(self):
    self.bfs10473(self.bfs10566, self.bfs10567)

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

  def bfs10567(self):
    AlertImpl(self.driver).accept()
    self.bfs10566()

  def bfs10576(self, condition_fn, timeout_secs=10, interval_secs=0.5):
    if ismethod(condition_fn):
      bfs10570 = (condition_fn.__self__ is not None)
      bfs10572 = getargspec(condition_fn).args
      bfs10573 = (len(bfs10572) - (1 if bfs10570 else 0)
)
    else:
      if (not isfunction(condition_fn)):
        condition_fn = condition_fn.__call__

      bfs10572 = getargspec(condition_fn).args
      bfs10573 = len(bfs10572)

    bfs10574 = (condition_fn if bfs10573 else (lambda driver: condition_fn()))

    wait = WebDriverWait(self.bfs10467(), timeout_secs, poll_frequency=interval_secs)
    wait.until(bfs10574)

  @bfs10444
  def bfs10575(self, window):
    from helium.api import Window
    if isinstance(window, str):
      window = WindowImpl(self.driver, window)
    elif isinstance(window, Window):
      window = window.bfs10472

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

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

  @bfs10444
  def bfs10601(self, element):
    from helium.api import HTMLElement
    if isinstance(element, HTMLElement):
      element = element.bfs10472

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

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

    bfs10600 = 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, bfs10600)


class bfs10554(object):
  def __init__(self, driver, file_path):
    self.driver = driver
    self.file_path = file_path
    self.bfs10602 = None
    self.bfs10603 = None

  def begin(self):
    self.bfs10605()
    try:
      self.bfs10602.send_keys(self.file_path)
    except:
      self.end()
      raise 


  def bfs10605(self):
    self.bfs10602 = 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 bfs10556(self):
    self.bfs10604('dragenter', to='document.body')
    self.bfs10603 = self.bfs10606('dragover', 'document', interval_msecs=300)
    self.bfs10603.start()

  def bfs10604(self, bfs10610, to):
    (bfs10607, args) = self.bfs10611(bfs10610, to)
    self.driver.execute_script(bfs10607, *args)

  def bfs10606(self, bfs10612, to, interval_msecs):
    (bfs10613, args) = self.bfs10611(bfs10612, to)
    return bfs10615(self.driver, bfs10613, args, interval_msecs)

  def bfs10611(self, bfs10614, to):
    bfs10616 = "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):
      bfs10616 = bfs10616.replace('arguments[2]', to)
      args = (self.bfs10602, bfs10614)
    else:
      args = (self.bfs10602, bfs10614, to.unwrap())

    return (bfs10616, args)

  def bfs10557(self, target):
    self.bfs10603.stop()
    self.bfs10604('drop', to=target)

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

    self.bfs10602 = None


class bfs10615(object):
  def __init__(self, driver, bfs10617, args, interval_msecs):
    self.driver = driver
    self.bfs10617 = bfs10617
    self.args = args
    self.interval_msecs = interval_msecs
    self.bfs10621 = None

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

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


class bfs10622(object):
  def __init__(self, driver):
    self.bfs10624 = None
    self.bfs10623 = driver

  def find_all(self):
    if self.bfs10625():
      yield self
    else:
      for bfs10626 in self.bfs10627():
        yield self.bfs10631(bfs10626)



  def bfs10625(self):
    return (self.bfs10624 is not None)

  def bfs10627(self):
    raise NotImplementedError()

  def bfs10631(self, bfs10630):
    bfs10632 = copy(self)
    bfs10632.bfs10624 = bfs10630
    return bfs10632

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


  @property
  def first_occurrence(self):
    if (not self.bfs10625()):
      self.bfs10633()

    return self.bfs10624

  def bfs10633(self):
    self.perform((lambda bfs10635: None))

  def perform(self, bfs10400):
    from helium.api import Config
    bfs10634 = (time() + Config.implicit_wait_secs)
    bfs10636 = self.bfs10637(bfs10400)
    while ((bfs10636 is None) and (time() < bfs10634)):
      bfs10636 = self.bfs10637(bfs10400)

    if (bfs10636 is not None):
      return bfs10636

    raise LookupError()

  def bfs10637(self, bfs10400):
    for bfs10641 in self.find_all():
      bfs10640 = bfs10641.first_occurrence
      try:
        bfs10400(bfs10640)
      except Exception as e:
        if self.bfs10642(e):
          continue
        else:
          raise 

      else:
        self.bfs10624 = bfs10640
        return bfs10640



  def bfs10642(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)):
        bfs10106.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 bfs10643(bfs10622):
  def __init__(self, driver, below=None, to_right_of=None, above=None, to_left_of=None):
    super(bfs10643, self).__init__(driver)
    self.below = self.bfs10645(below)
    self.to_right_of = self.bfs10645(to_right_of)
    self.above = self.bfs10645(above)
    self.to_left_of = self.bfs10645(to_left_of)
    self.bfs10644 = bfs10150()

  def bfs10645(self, element):
    if isinstance(element, str):
      return TextImpl(self.bfs10623, element)

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

    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.bfs10237

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

  @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 bfs10627(self):
    bfs10646 = self.bfs10647()
    for bfs10650 in bfs10416(self.bfs10623):
      for bfs10651 in self.bfs10653():
        if self.bfs10652(bfs10651, bfs10646):
          yield bfs10651




  def bfs10647(self):
    bfs10636 = []
    if self.below:
      bfs10636.append(list(map((lambda bfs10654: bfs10654.location.is_above), self.below.bfs10627())))

    if self.to_right_of:
      bfs10636.append(list(map((lambda bfs10656: bfs10656.location.is_to_left_of), self.to_right_of.bfs10627())))

    if self.above:
      bfs10636.append(list(map((lambda bfs10655: bfs10655.location.is_below), self.above.bfs10627())))

    if self.to_left_of:
      bfs10636.append(list(map((lambda bfs10657: bfs10657.location.is_to_right_of), self.to_left_of.bfs10627())))

    return bfs10636

  def bfs10652(self, bfs10660, bfs10661):
    return (bfs10660.is_displayed() and self.bfs10662(bfs10660, bfs10661))

  def bfs10662(self, element, bfs10663):
    for bfs10665 in bfs10663:
      bfs10664 = False
      for bfs10666 in bfs10665:
        if bfs10666(element.location):
          bfs10664 = True
          break


      if (not bfs10664):
        return False


    return True

  def bfs10653(self):
    raise NotImplementedError()

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


class SImpl(bfs10643):
  def __init__(self, driver, bfs10667):
    super(bfs10643, self).__init__(driver)
    self.bfs10667 = bfs10667

  def bfs10653(self):
    wrap = (lambda bfs10671: list(map(bfs10415, bfs10671)))
    if self.bfs10667.startswith('@'):
      return wrap(self.bfs10623.find_elements_by_name(self.bfs10667[1:]))

    if self.bfs10667.startswith('//'):
      return wrap(self.bfs10623.find_elements_by_xpath(self.bfs10667))

    return wrap(self.bfs10623.find_elements_by_css_selector(self.bfs10667))

  def bfs10647(self):
    return []


class bfs10672(bfs10643):
  def bfs10653(self):
    bfs10674 = self.bfs10673()
    bfs10106.debug(('Looking for HTML element using xpath: %s.' % bfs10674))
    return self.bfs10675(list(map(bfs10415, self.bfs10623.find_elements_by_xpath(bfs10674))))

  def bfs10675(self, bfs10677):
    bfs10676 = []
    for bfs10700 in bfs10677:
      try:
        key = self.bfs10702(bfs10700)
      except StaleElementReferenceException:
        pass
      else:
        bfs10676.append((key, bfs10700))


    bfs10701 = (lambda bfs10703: bfs10703[0])
    bfs10676.sort(key=bfs10701)
    bfs10705 = (lambda bfs10704: bfs10704[1])
    return list(map(bfs10705, bfs10676))

  def bfs10673(self):
    raise NotImplementedError()

  def bfs10702(self, web_element):
    return (self.bfs10623.bfs10402(web_element) + 1)


class bfs10706(bfs10672):
  def __init__(self, driver, text=None, **bfs10707):
    super(bfs10706, self).__init__(driver, **bfs10707)
    self.search_text = text

  def bfs10673(self):
    bfs10711 = (('//' + self.bfs10710()) + predicate(self.bfs10644.bfs10137('.', self.search_text)))
    return ('%s[not(self::script)][not(.%s)]' % (bfs10711, bfs10711))

  def bfs10710(self):
    return '*'


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

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

  def bfs10673(self):
    bfs10714 = [(super(TextImpl, self).bfs10673() + '[not(self::option)]'), ButtonImpl(self.bfs10623, self.search_text).bfs10713(), LinkImpl(self.bfs10623, self.search_text).bfs10673()]
    if self.include_free_text:
      bfs10714.append(bfs10715(self.bfs10623, self.search_text).bfs10673())

    return ' | '.join(bfs10714)


class bfs10715(bfs10706):
  def bfs10710(self):
    return 'text()'

  def bfs10673(self):
    return (super(bfs10715, self).bfs10673() + '/..')


class LinkImpl(bfs10706):
  def bfs10710(self):
    return 'a'

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


class ListItemImpl(bfs10706):
  def bfs10710(self):
    return 'li'


class ButtonImpl(bfs10706):
  def bfs10710(self):
    return 'button'

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

  def bfs10673(self):
    bfs10716 = self.bfs10644.bfs10137('@aria-label', self.search_text)
    bfs10720 = self.bfs10644.bfs10137('.', self.search_text)
    bfs10722 = bfs10143(bfs10716, bfs10720)
    return ' | '.join([super(ButtonImpl, self).bfs10673(), self.bfs10713(), ("//*[@role='button']" + bfs10722), ('//button' + predicate(bfs10716))])

  def bfs10713(self):
    if self.search_text:
      bfs10721 = self.bfs10644.bfs10137('@value', self.search_text)
      bfs10723 = self.bfs10644.bfs10137('@label', self.search_text)
      bfs10724 = self.bfs10644.bfs10137('@aria-label', self.search_text)
      bfs10725 = self.bfs10644.bfs10137('@title', self.search_text)
      bfs10727 = bfs10143(bfs10721, bfs10723, bfs10724, bfs10725)
    else:
      bfs10727 = ''

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


class ImageImpl(bfs10672):
  def __init__(self, driver, alt, **bfs10726):
    super(ImageImpl, self).__init__(driver, **bfs10726)
    self.alt = alt

  def bfs10673(self):
    return ('//img' + predicate(self.bfs10644.bfs10137('@alt', self.alt)))


class bfs10730(bfs10643):
  bfs10731 = 1.5
  def __init__(self, driver, label=None, **bfs10733):
    super(bfs10730, self).__init__(driver, **bfs10733)
    self.label = label

  def bfs10653(self):
    if (not self.label):
      bfs10732 = self.bfs10734()
    else:
      bfs10735 = TextImpl(self.bfs10623, self.label, include_free_text=False).bfs10653()
      if bfs10735:
        bfs10732 = list(self.bfs10736(self.bfs10734(), bfs10735))
      else:
        bfs10732 = self.bfs10740()


    return sorted(bfs10732, key=self.bfs10623.bfs10402)

  def bfs10734(self, bfs10737=None):
    if (bfs10737 is None):
      bfs10737 = self.bfs10673()

    return list(map(bfs10415, self.bfs10623.find_elements_by_xpath(bfs10737)))

  def bfs10740(self):
    bfs10741 = [bfs10137.strip().lstrip('/') for bfs10137 in self.bfs10673().split('|')]
    bfs10742 = ('//text()' + predicate(self.bfs10644.bfs10137('.', self.label)))
    bfs10137 = ' | '.join([(((bfs10742 + '/following::') + bfs10744) + '[1]') for bfs10744 in bfs10741])
    return self.bfs10734(bfs10137)

  def bfs10673(self):
    raise NotImplementedError()

  def bfs10743(self):
    return 'to_right_of'

  def bfs10745(self):
    return 'below'

  def bfs10736(self, bfs10746, bfs10750):
    for (label, bfs10747) in self.bfs10751(bfs10746, bfs10750):
      yield bfs10747
      bfs10750.remove(label)
      bfs10746.remove(bfs10747)

    bfs10752 = self.bfs10754(bfs10746, bfs10750)
    bfs10752 = self.bfs10753(bfs10752)
    self.bfs10755(bfs10752)
    for bfs10756 in list(bfs10752.values()):
      assert (len(bfs10756) <= 1)
      if bfs10756:
        yield next(iter(bfs10756))



  def bfs10751(self, bfs10757, bfs10760):
    for label in bfs10760:
      if (label.tag_name == 'label'):
        bfs10762 = label.get_attribute('for')
        if bfs10762:
          for bfs10761 in bfs10757:
            bfs10763 = bfs10761.get_attribute('id')
            if (bfs10763.lower() == bfs10762.lower()):
              yield (label, bfs10761)






  def bfs10754(self, bfs10765, bfs10764):
    bfs10766 = {}
    for label in bfs10764:
      for bfs10770 in bfs10765:
        if self.bfs10767(bfs10770, label):
          if (label not in bfs10766):
            bfs10766[label] = set()

          bfs10766[label].add(bfs10770)



    return bfs10766

  def bfs10767(self, bfs10771, label):
    if bfs10771.location.bfs10301(label.location):
      return True

    bfs10772 = self.bfs10743()
    bfs10773 = self.bfs10745()
    return ((label.location.bfs10326(bfs10771.location) <= 150) and (bfs10771.location.bfs10316(bfs10772, label.location) or bfs10771.location.bfs10316(bfs10773, label.location)))

  def bfs10753(self, bfs10775):
    bfs10774 = bfs10430(bfs10775)
    self.bfs10755(bfs10774)
    return bfs10430(bfs10774)

  def bfs10755(self, bfs10776):
    for (bfs11000, bfs10777) in list(bfs10776.items()):
      if bfs10777:
        bfs10776[bfs11000] = set([self.bfs11001(bfs11000, bfs10777)])



  def bfs11001(self, bfs11002, bfs11004):
    bfs11003 = iter(bfs11004)
    bfs11005 = next(bfs11003)
    bfs11007 = self.bfs11006(bfs11005, bfs11002)
    for element in bfs11003:
      bfs11010 = self.bfs11006(element, bfs11002)
      if (bfs11010 < bfs11007):
        bfs11005 = element
        bfs11007 = bfs11010


    return bfs11005

  def bfs11006(self, bfs11012, bfs11011):
    bfs11013 = bfs11012.location
    bfs11014 = bfs11011.location
    if bfs11013.bfs10316(self.bfs10745(), bfs11014):
      bfs11015 = self.bfs10731
    else:
      bfs11015 = 1

    return (bfs11015 * bfs11013.bfs10326(bfs11014))


class bfs11016(bfs10643):
  def __init__(self, driver, *args, **bfs10454):
    super(bfs11016, self).__init__(driver, **bfs10454)
    self.args = ([driver] + list(args))
    self.bfs10454 = bfs10454
    self.bfs11020 = None

  @property
  def bfs11017(self):
    if (self.bfs11020 is None):
      self.bfs10633()

    return self.bfs11020

  def find_all(self):
    bfs11021 = []
    for element in self.bfs11023():
      for bfs11022 in element.find_all():
        if (self.bfs11020 is None):
          self.bfs11020 = element

        if (bfs11022 not in bfs11021):
          yield bfs11022
          bfs11021.append(bfs11022)




  def bfs11023(self):
    for bfs11024 in self.bfs11025():
      yield bfs11024(*self.args, **self.bfs10454)


  def bfs11025(self):
    raise NotImplementedError()


class bfs10510(bfs11016):
  def __init__(self, driver, text, **bfs11026):
    super(bfs10510, self).__init__(driver, text, **bfs11026)

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


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

  def bfs11025(self):
    return [bfs11031, bfs11030, bfs11032]

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

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

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


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

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

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

  def bfs10673(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 bfs11032(bfs10730):
  @property
  def value(self):
    return self.first_occurrence.text

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

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

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


class bfs11031(bfs10672):
  def __init__(self, driver, label, **bfs11033):
    super(bfs11031, self).__init__(driver, **bfs11033)
    self.label = label

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

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

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

  def bfs10673(self):
    return ('(%s)%s' % (bfs11030(self.label).bfs10673(), predicate(self.bfs10644.bfs10137('@placeholder', self.label))))


class bfs10562(bfs10730):
  def bfs10673(self):
    return "//input[@type='file']"


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

  def bfs11025(self):
    return [bfs11036, bfs11035]

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

  @property
  def value(self):
    bfs11037 = self.bfs11040.first_selected_option
    if bfs11037:
      return bfs11037.text

    return None

  @property
  def options(self):
    return [bfs11042.text for bfs11042 in self.bfs11040.options]

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


class bfs11036(bfs10730):
  def bfs10673(self):
    return '//select | //input[@list]'


class bfs11035(bfs10706):
  def bfs10710(self):
    return 'option'

  def bfs10673(self):
    bfs11041 = super(bfs11035, self).bfs10673()
    return (bfs11041 + '/ancestor::select[1]')

  def bfs10653(self):
    bfs11043 = super(bfs11035, self).bfs10653()
    bfs11044 = []
    for bfs11045 in bfs11043:
      for bfs11047 in Select(bfs11045.unwrap()).all_selected_options:
        if self.bfs10644.text(bfs11047.text, self.search_text):
          bfs11044.append(bfs11045)
          break



    return bfs11044


class CheckBoxImpl(bfs10730):
  def is_enabled(self):
    return self.bfs10670()

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

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

  def bfs10743(self):
    return 'to_left_of'

  def bfs10745(self):
    return 'to_right_of'


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

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

  def bfs10743(self):
    return 'to_left_of'

  def bfs10745(self):
    return 'to_right_of'


class WindowImpl(bfs10622):
  def __init__(self, driver, title=None):
    super(WindowImpl, self).__init__(driver)
    self.bfs11046 = title

  def bfs10627(self):
    bfs11050 = []
    for handle in self.bfs10623.window_handles:
      window = WindowImpl.bfs11051(self.bfs10623, handle)
      if (self.bfs11046 is None):
        bfs11050.append((0, window))
      else:
        title = window.title
        if title.startswith(self.bfs11046):
          bfs11053 = (len(title) - len(self.bfs11046))
          bfs11050.append((bfs11053, window))



    bfs11053 = (lambda bfs11052: bfs11052[0])
    bfs11050.sort(key=bfs11053)
    for (bfs11053, window) in bfs11050:
      yield window


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

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

  class bfs11051(object):
    def __init__(self, driver, handle):
      self.driver = driver
      self.handle = handle
      self.bfs11054 = None

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


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


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




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

  def bfs10627(self):
    bfs11055 = self.bfs10623.switch_to.alert
    try:
      text = bfs11055.text
      if ((self.search_text is None) or text.startswith(self.search_text)):
        yield bfs11055

    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)):
        bfs10106.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)


