from bfs.bfs10135.errors import bfs10136
from copy import copy
from decorator import decorator
from errno import ESRCH as bfs10420, EACCES as bfs10417
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
from helium.bfs10077.bfs10410 import bfs10415
from helium.bfs10077.bfs10414 import bfs10416
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, NoSuchFrameException, 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
bfs10107 = logging.getLogger(__name__)
bfs10107.setLevel(logging.INFO)
@decorator
def bfs10427(bfs10400, self, *args, **bfs10421):
  if (self.driver.bfs10377() and AlertImpl(self.driver).exists()):
    return bfs10400(self, *args, **bfs10421)

  bfs10423 = self.driver.window_handles[:]
  bfs10422 = bfs10400(self, *args, **bfs10421)
  if (not (self.driver.bfs10377() and AlertImpl(self.driver).exists())):
    bfs10424 = [bfs10425 for bfs10425 in self.driver.window_handles if (bfs10425 not in bfs10423) ]
    if bfs10424:
      self.driver.switch_to.window(bfs10424[0])


  return bfs10422

@decorator
def bfs10430(bfs10400, *args, **bfs10426):
  try:
    return bfs10400(*args, **bfs10426)
  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, bfs10432, bfs10431, bfs10433=None):
    self.bfs10432 = bfs10432
    self.license = bfs10431
    self.bfs10433 = bfs10433
    self.driver = None

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

  def bfs10443(self, url=None):
    bfs10434 = self.bfs10436()
    bfs10440 = ChromeOptions()
    bfs10440.add_argument('--test-type')
    bfs10437 = {'chrome_options': bfs10440}
    if exists(bfs10434):
      if (not access(bfs10434, X_OK)):
        try:
          bfs10416(bfs10434)
        except:
          raise RuntimeError(('The Chrome driver located at %s is not executable.' % bfs10434))


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

    bfs10167()
    bfs10441 = Chrome(**bfs10437)
    atexit.register((lambda : self.bfs10442(bfs10441.service)))
    return self._start(bfs10441, url)

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

    return self.bfs10432.bfs10063(bfs10156(), 'webdrivers', bfs10444)

  def bfs10442(self, service):
    if hasattr(service, 'process'):
      try:
        service.process.kill()
      except OSError, e:
        if (e.errno not in (bfs10420, bfs10417)):
          raise 




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

    bfs10447 = Ie(**bfs10437)
    atexit.register((lambda : self.bfs10442(bfs10447.iedriver)))
    return self._start(bfs10447, url)

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

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

    return self.bfs10453()

  @bfs10427
  @bfs10430
  def bfs10451(self, url):
    if ('://' not in url):
      url = ('http://' + url)

    self.driver.get(url)

  def bfs10452(self, driver):
    self.bfs10454(driver)
    self.driver = bfs10371(driver)

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



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


  @bfs10427
  @bfs10430
  def bfs10462(self, text, into=None):
    if (into is not None):
      from helium.api import GUIElement
      if isinstance(into, GUIElement):
        into = into.bfs10455


    self.bfs10457(self.bfs10461, self.bfs10460, text, into=into)

  def bfs10461(self, text, into=None):
    if into:
      if isinstance(into, basestring):
        into = TextFieldImpl(self.driver, into)

      def _write(bfs10464):
        if (hasattr(bfs10464, 'clear') and callable(bfs10464.clear)):
          bfs10464.clear()

        bfs10464.send_keys(text)

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


  def bfs10460(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 bfs10457(self, bfs10465, bfs10466, *args, **bfs10467):
    if (self.driver.bfs10375() or (not AlertImpl(self.driver).exists())):
      try:
        return bfs10465(*args, **bfs10467)
      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 bfs10466(*args, **bfs10467)

  @bfs10427
  @bfs10430
  def bfs10471(self, key):
    self.driver.switch_to.active_element.send_keys(key)

  def bfs10474(self, element):
    element = self.bfs10470(element)
    click = (lambda bfs10472: bfs10472.click())
    self.bfs10473(element, click, click)

  def bfs10470(self, bfs10464):
    from helium.api import HTMLElement
    if isinstance(bfs10464, basestring):
      bfs10464 = bfs10476(self.driver, bfs10464)
    elif isinstance(bfs10464, HTMLElement):
      bfs10464 = bfs10464.bfs10455

    return bfs10464

  @bfs10427
  @bfs10430
  def bfs10473(self, element, bfs10475, bfs10477):
    offset = None
    from helium.api import Point
    if isinstance(element, Point):
      (element, offset) = self.bfs10500(element)

    if (offset is not None):
      bfs10373 = (lambda bfs10501: bfs10477(self.driver.bfs10373().move_to_element_with_offset(bfs10501, *offset)).perform())
    else:
      bfs10373 = (lambda bfs10503: bfs10475(bfs10503))

    self.bfs10463(element, bfs10373)

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

    return (element, offset)

  def bfs10505(self, element):
    element = self.bfs10470(element)
    self.bfs10473(element, (lambda bfs10504: self.driver.bfs10373().double_click(bfs10504).perform()), (lambda bfs10506: bfs10506.double_click()))

  def bfs10510(self, element, to):
    self.bfs10507(element)
    self.bfs10511(to)

  def bfs10507(self, element):
    element = self.bfs10470(element)
    self.bfs10473(element, (lambda bfs10512: self.driver.bfs10373().click_and_hold(bfs10512).perform()), (lambda bfs10513: bfs10513.click_and_hold()))

  def bfs10511(self, element):
    element = self.bfs10470(element)
    self.bfs10473(element, (lambda bfs10515: self.driver.bfs10373().move_to_element(bfs10515).release().perform()), (lambda bfs10514: bfs10514.release()))

  @bfs10430
  def bfs10520(self, predicate):
    return [predicate.bfs10516(bfs10517) for bfs10517 in predicate.bfs10455.find_all()]

  def bfs10523(self, num_pixels):
    self.bfs10521(0, num_pixels)

  def bfs10522(self, num_pixels):
    self.bfs10521(0, (-num_pixels))

  def bfs10524(self, num_pixels):
    self.bfs10521(num_pixels, 0)

  def bfs10525(self, num_pixels):
    self.bfs10521((-num_pixels), 0)

  @bfs10430
  def bfs10521(self, bfs10527, bfs10526):
    self.driver.execute_script('window.scrollBy(arguments[0], arguments[1]);', bfs10527, bfs10526)

  def bfs10532(self, element):
    element = self.bfs10470(element)
    self.bfs10473(element, (lambda bfs10530: self.driver.bfs10373().move_to_element(bfs10530).perform()), (lambda bfs10531: bfs10531))

  def bfs10535(self, element):
    element = self.bfs10470(element)
    self.bfs10473(element, (lambda bfs10534: self.driver.bfs10373().context_click(bfs10534).perform()), (lambda bfs10533: bfs10533.context_click()))

  @bfs10427
  @bfs10430
  def bfs10540(self, combo_box, value):
    from helium.api import ComboBox
    if isinstance(combo_box, basestring):
      combo_box = ComboBoxImpl(self.driver, combo_box)
    elif isinstance(combo_box, ComboBox):
      combo_box = combo_box.bfs10455

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

    self.bfs10463(combo_box, bfs10536)

  def bfs10463(self, bfs10537, bfs10373):
    if (hasattr(bfs10537, 'perform') and callable(bfs10537.perform)):
      self.driver.bfs10372 = bfs10537.perform(bfs10373)
    else:
      if isinstance(bfs10537, WebElement):
        bfs10537 = bfs10407(bfs10537)

      bfs10373(bfs10537)
      self.driver.bfs10372 = bfs10537


  @bfs10430
  def bfs10546(self, file_path, to):
    to = self.bfs10470(to)
    drag_and_drop = bfs10541(self.driver, file_path)
    drag_and_drop.begin()
    try:
      drag_and_drop.bfs10543()
      self.bfs10463(to, (lambda bfs10542: drag_and_drop.bfs10544(bfs10542)))
    finally:
      drag_and_drop.end()


  def bfs10551(self, file_path, to=None):
    if (to is None):
      to = bfs10545(self.driver)
    elif isinstance(to, basestring):
      to = bfs10545(self.driver, to)

    bfs10547 = (lambda bfs10550: bfs10550.send_keys(file_path))
    self.bfs10473(to, bfs10547, bfs10547)

  def bfs10555(self):
    self.bfs10457(self.bfs10552, self.bfs10553)

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

  def bfs10553(self):
    AlertImpl(self.driver).accept()
    self.bfs10552()

  def bfs10561(self, condition_fn, timeout_secs=10, interval_secs=0.5):
    if ismethod(condition_fn):
      bfs10554 = (condition_fn.im_self is not None)
      bfs10556 = getargspec(condition_fn).args
      bfs10560 = (len(bfs10556) - (1 if bfs10554 else 0)
)
    else:
      if (not isfunction(condition_fn)):
        condition_fn = condition_fn.__call__

      bfs10556 = getargspec(condition_fn).args
      bfs10560 = len(bfs10556)

    bfs10557 = (condition_fn if bfs10560 else (lambda driver: condition_fn()))

    wait = WebDriverWait(self.bfs10453(), timeout_secs, poll_frequency=interval_secs)
    wait.until(bfs10557)

  @bfs10430
  def bfs10562(self, window):
    from helium.api import Window
    if isinstance(window, basestring):
      window = WindowImpl(self.driver, window)
    elif isinstance(window, Window):
      window = window.bfs10455

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

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

  @bfs10430
  def bfs10564(self, element):
    from helium.api import HTMLElement
    if isinstance(element, HTMLElement):
      element = element.bfs10455

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

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

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


class bfs10541(object):
  def __init__(self, driver, file_path):
    self.driver = driver
    self.file_path = file_path
    self.bfs10566 = None
    self.bfs10567 = None

  def begin(self):
    self.bfs10571()
    try:
      self.bfs10566.send_keys(self.file_path)
    except:
      self.end()
      raise 


  def bfs10571(self):
    self.bfs10566 = 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 bfs10543(self):
    self.bfs10570('dragenter', to='document.body')
    self.bfs10567 = self.bfs10572('dragover', 'document', interval_msecs=300)
    self.bfs10567.start()

  def bfs10570(self, bfs10573, to):
    (bfs10574, args) = self.bfs10576(bfs10573, to)
    self.driver.execute_script(bfs10574, *args)

  def bfs10572(self, bfs10575, to, interval_msecs):
    (bfs10577, args) = self.bfs10576(bfs10575, to)
    return bfs10600(self.driver, bfs10577, args, interval_msecs)

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

    return (bfs10602, args)

  def bfs10544(self, target):
    self.bfs10567.stop()
    self.bfs10570('drop', to=target)

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

    self.bfs10566 = None


class bfs10600(object):
  def __init__(self, driver, bfs10603, args, interval_msecs):
    self.driver = driver
    self.bfs10603 = bfs10603
    self.args = args
    self.interval_msecs = interval_msecs
    self.bfs10605 = None

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

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


class bfs10606(object):
  def __init__(self, driver):
    self.bfs10610 = None
    self.bfs10607 = driver

  def find_all(self):
    if self.bfs10611():
      yield self
    else:
      for bfs10612 in self.bfs10613():
        yield self.bfs10615(bfs10612)



  def bfs10611(self):
    return (self.bfs10610 is not None)

  def bfs10613(self):
    raise NotImplementedError()

  def bfs10615(self, bfs10614):
    bfs10616 = copy(self)
    bfs10616.bfs10610 = bfs10614
    return bfs10616

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


  @property
  def first_occurrence(self):
    if (not self.bfs10611()):
      self.bfs10617()

    return self.bfs10610

  def bfs10617(self):
    self.perform((lambda bfs10621: None))

  def perform(self, bfs10373):
    from helium.api import Config
    bfs10620 = (time() + Config.implicit_wait_secs)
    bfs10622 = self.bfs10624(bfs10373)
    while ((bfs10622 is None) and (time() < bfs10620)):
      bfs10622 = self.bfs10624(bfs10373)

    if (bfs10622 is not None):
      return bfs10622

    raise LookupError()

  def bfs10624(self, bfs10373):
    for bfs10623 in self.find_all():
      bfs10625 = bfs10623.first_occurrence
      try:
        bfs10373(bfs10625)
      except Exception, e:
        if self.bfs10626(e):
          continue
        else:
          raise 

      else:
        self.bfs10610 = bfs10625
        return bfs10625



  def bfs10626(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 bfs10627(bfs10606):
  def __init__(self, driver, below=None, to_right_of=None, above=None, to_left_of=None):
    super(bfs10627, self).__init__(driver)
    self.below = self.bfs10631(below)
    self.to_right_of = self.bfs10631(to_right_of)
    self.above = self.bfs10631(above)
    self.to_left_of = self.bfs10631(to_left_of)
    self.bfs10630 = bfs10151()

  def bfs10631(self, element):
    if isinstance(element, basestring):
      return TextImpl(self.bfs10607, element)

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

    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 bfs10613(self):
    for bfs10632 in self.bfs10633():
      if bfs10632.is_displayed():
        yield bfs10632


    for bfs10635 in self.bfs10607.find_elements_by_tag_name('iframe'):
      try:
        self.bfs10607.switch_to.frame(bfs10635)
      except (NoSuchFrameException, StaleElementReferenceException):
        continue
      else:
        for bfs10632 in self.bfs10633():
          if bfs10632.is_displayed():
            yield bfs10632


        self.bfs10607.switch_to.default_content()



  def bfs10633(self):
    bfs10634 = self.bfs10636()
    for bfs10637 in self.bfs10641():
      if self.bfs10640(bfs10637, bfs10634):
        yield bfs10637



  def bfs10636(self):
    bfs10622 = []
    if self.below:
      bfs10622.append(map((lambda bfs10642: bfs10642.location.is_above), self.below.bfs10641()))

    if self.to_right_of:
      bfs10622.append(map((lambda bfs10643: bfs10643.location.is_to_left_of), self.to_right_of.bfs10641()))

    if self.above:
      bfs10622.append(map((lambda bfs10645: bfs10645.location.is_below), self.above.bfs10641()))

    if self.to_left_of:
      bfs10622.append(map((lambda bfs10644: bfs10644.location.is_to_right_of), self.to_left_of.bfs10641()))

    return bfs10622

  def bfs10640(self, element, bfs10646):
    for bfs10647 in bfs10646:
      bfs10650 = False
      for bfs10651 in bfs10647:
        if bfs10651(element.location):
          bfs10650 = True
          break


      if (not bfs10650):
        return False


    return True

  def bfs10641(self):
    raise NotImplementedError()

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


class SImpl(bfs10627):
  def __init__(self, driver, bfs10652):
    super(bfs10627, self).__init__(driver)
    self.bfs10652 = bfs10652

  def bfs10641(self):
    wrap = (lambda bfs10654: map(bfs10407, bfs10654))
    if self.bfs10652.startswith('@'):
      return wrap(self.bfs10607.find_elements_by_name(self.bfs10652[1:]))

    if self.bfs10652.startswith('//'):
      return wrap(self.bfs10607.find_elements_by_xpath(self.bfs10652))

    return wrap(self.bfs10607.find_elements_by_css_selector(self.bfs10652))

  def bfs10636(self):
    return []


class bfs10656(bfs10627):
  def bfs10641(self):
    bfs10655 = self.bfs10657()
    bfs10107.debug(('Looking for HTML element using xpath: %s.' % bfs10655))
    return self.bfs10660(map(bfs10407, self.bfs10607.find_elements_by_xpath(bfs10655)))

  def bfs10660(self, bfs10661):
    bfs10662 = []
    for bfs10663 in bfs10661:
      try:
        key = self.bfs10665(bfs10663)
      except StaleElementReferenceException:
        pass
      else:
        bfs10662.append((key, bfs10663))


    bfs10664 = (lambda bfs10666: bfs10666[0])
    bfs10662.sort(key=bfs10664)
    bfs10670 = (lambda bfs10667: bfs10667[1])
    return map(bfs10670, bfs10662)

  def bfs10657(self):
    raise NotImplementedError()

  def bfs10665(self, web_element):
    return (self.bfs10607.bfs10376(web_element) + 1)


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

  def bfs10657(self):
    bfs10674 = (('//' + self.bfs10673()) + predicate(self.bfs10630.bfs10140('.', self.search_text)))
    return ('%s[not(self::script)][not(.%s)]' % (bfs10674, bfs10674))

  def bfs10673(self):
    return '*'


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

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

  def bfs10657(self):
    bfs10677 = [(super(TextImpl, self).bfs10657() + '[not(self::option)]'), ButtonImpl(self.bfs10607, self.search_text).bfs10676(), LinkImpl(self.bfs10607, self.search_text).bfs10657()]
    if self.include_free_text:
      bfs10677.append(bfs10700(self.bfs10607, self.search_text).bfs10657())

    return ' | '.join(bfs10677)


class bfs10700(bfs10671):
  def bfs10673(self):
    return 'text()'

  def bfs10657(self):
    return (super(bfs10700, self).bfs10657() + '/..')


class LinkImpl(bfs10671):
  def bfs10673(self):
    return 'a'

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


class ListItemImpl(bfs10671):
  def bfs10673(self):
    return 'li'


class ButtonImpl(bfs10671):
  def bfs10673(self):
    return 'button'

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

  def bfs10657(self):
    bfs10701 = self.bfs10630.bfs10140('@aria-label', self.search_text)
    bfs10703 = self.bfs10630.bfs10140('.', self.search_text)
    bfs10705 = bfs10147(bfs10701, bfs10703)
    return ' | '.join([super(ButtonImpl, self).bfs10657(), self.bfs10676(), ("//*[@role='button']" + bfs10705), ('//button' + predicate(bfs10701))])

  def bfs10676(self):
    if self.search_text:
      bfs10704 = self.bfs10630.bfs10140('@value', self.search_text)
      bfs10706 = self.bfs10630.bfs10140('@label', self.search_text)
      bfs10707 = self.bfs10630.bfs10140('@aria-label', self.search_text)
      bfs10711 = self.bfs10630.bfs10140('@title', self.search_text)
      bfs10710 = bfs10147(bfs10704, bfs10706, bfs10707, bfs10711)
    else:
      bfs10710 = ''

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


class ImageImpl(bfs10656):
  def __init__(self, driver, alt, **bfs10712):
    super(ImageImpl, self).__init__(driver, **bfs10712)
    self.alt = alt

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


class bfs10714(bfs10627):
  bfs10713 = 1.5
  def __init__(self, driver, label=None, **bfs10715):
    super(bfs10714, self).__init__(driver, **bfs10715)
    self.label = label

  def bfs10641(self):
    if (not self.label):
      bfs10717 = self.bfs10716()
    else:
      bfs10720 = TextImpl(self.bfs10607, self.label, include_free_text=False).bfs10641()
      if bfs10720:
        bfs10717 = list(self.bfs10722(self.bfs10716(), bfs10720))
      else:
        bfs10717 = self.bfs10721()


    return sorted(bfs10717, key=self.bfs10607.bfs10376)

  def bfs10716(self, bfs10723=None):
    if (bfs10723 is None):
      bfs10723 = self.bfs10657()

    return map(bfs10407, self.bfs10607.find_elements_by_xpath(bfs10723))

  def bfs10721(self):
    bfs10724 = [bfs10140.strip().lstrip('/') for bfs10140 in self.bfs10657().split('|')]
    bfs10725 = ('//text()' + predicate(self.bfs10630.bfs10140('.', self.label)))
    bfs10140 = ' | '.join([(((bfs10725 + '/following::') + bfs10727) + '[1]') for bfs10727 in bfs10724])
    return self.bfs10716(bfs10140)

  def bfs10657(self):
    raise NotImplementedError()

  def bfs10726(self):
    return 'to_right_of'

  def bfs10730(self):
    return 'below'

  def bfs10722(self, bfs10731, bfs10733):
    for (label, bfs10732) in self.bfs10734(bfs10731, bfs10733):
      yield bfs10732
      bfs10733.remove(label)
      bfs10731.remove(bfs10732)

    bfs10735 = self.bfs10736(bfs10731, bfs10733)
    bfs10735 = self.bfs10740(bfs10735)
    self.bfs10737(bfs10735)
    for bfs10741 in bfs10735.values():
      assert (len(bfs10741) <= 1)
      if bfs10741:
        yield next(iter(bfs10741))



  def bfs10734(self, bfs10742, bfs10744):
    for label in bfs10744:
      if (label.tag_name == 'label'):
        bfs10743 = label.get_attribute('for')
        if bfs10743:
          for bfs10745 in bfs10742:
            bfs10746 = bfs10745.get_attribute('id')
            if (bfs10746.lower() == bfs10743.lower()):
              yield (label, bfs10745)






  def bfs10736(self, bfs10750, bfs10747):
    bfs10751 = {}
    for label in bfs10747:
      for bfs10752 in bfs10750:
        if self.bfs10754(bfs10752, label):
          if (label not in bfs10751):
            bfs10751[label] = set()

          bfs10751[label].add(bfs10752)



    return bfs10751

  def bfs10754(self, bfs10753, label):
    if bfs10753.location.bfs10274(label.location):
      return True

    bfs10755 = self.bfs10726()
    bfs10756 = self.bfs10730()
    return ((label.location.bfs10323(bfs10753.location) <= 150) and (bfs10753.location.bfs10312(bfs10755, label.location) or bfs10753.location.bfs10312(bfs10756, label.location)))

  def bfs10740(self, bfs10757):
    bfs10760 = bfs10415(bfs10757)
    self.bfs10737(bfs10760)
    return bfs10415(bfs10760)

  def bfs10737(self, bfs10762):
    for (bfs10761, bfs10763) in bfs10762.items():
      if bfs10763:
        bfs10762[bfs10761] = set([self.bfs10765(bfs10761, bfs10763)])



  def bfs10765(self, bfs10764, bfs10766):
    bfs10770 = iter(bfs10766)
    bfs10767 = next(bfs10770)
    bfs10771 = self.bfs10772(bfs10767, bfs10764)
    for element in bfs10770:
      bfs10773 = self.bfs10772(element, bfs10764)
      if (bfs10773 < bfs10771):
        bfs10767 = element
        bfs10771 = bfs10773


    return bfs10767

  def bfs10772(self, bfs10775, bfs10774):
    bfs10776 = bfs10775.location
    bfs11000 = bfs10774.location
    if bfs10776.bfs10312(self.bfs10730(), bfs11000):
      bfs10777 = self.bfs10713
    else:
      bfs10777 = 1

    return (bfs10777 * bfs10776.bfs10323(bfs11000))


class bfs11001(bfs10627):
  def __init__(self, driver, *args, **bfs10437):
    super(bfs11001, self).__init__(driver, **bfs10437)
    self.args = ([driver] + list(args))
    self.bfs10437 = bfs10437
    self.bfs11002 = None

  @property
  def bfs11004(self):
    if (self.bfs11002 is None):
      self.bfs10617()

    return self.bfs11002

  def find_all(self):
    bfs11003 = []
    for element in self.bfs11005():
      for bfs11007 in element.find_all():
        if (self.bfs11002 is None):
          self.bfs11002 = element

        if (bfs11007 not in bfs11003):
          yield bfs11007
          bfs11003.append(bfs11007)




  def bfs11005(self):
    for bfs11006 in self.bfs11010():
      yield bfs11006(*self.args, **self.bfs10437)


  def bfs11010(self):
    raise NotImplementedError()


class bfs10476(bfs11001):
  def __init__(self, driver, text, **bfs11012):
    super(bfs10476, self).__init__(driver, text, **bfs11012)

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


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

  def bfs11010(self):
    return [bfs11013, bfs11014, bfs11015]

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

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

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


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

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

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

  def bfs10657(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')


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

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

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

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


class bfs11013(bfs10656):
  def __init__(self, driver, label, **bfs11016):
    super(bfs11013, self).__init__(driver, **bfs11016)
    self.label = label

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

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

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

  def bfs10657(self):
    return ('(%s)%s' % (bfs11014(self.label).bfs10657(), predicate(self.bfs10630.bfs10140('@placeholder', self.label))))


class bfs10545(bfs10714):
  def bfs10657(self):
    return "//input[@type='file']"


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

  def bfs11010(self):
    return [bfs11017, bfs11021]

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

  @property
  def value(self):
    bfs11023 = self.bfs11022.first_selected_option
    if bfs11023:
      return bfs11023.text

    return None

  @property
  def options(self):
    return [bfs11024.text for bfs11024 in self.bfs11022.options]

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


class bfs11017(bfs10714):
  def bfs10657(self):
    return '//select | //input[@list]'


class bfs11021(bfs10671):
  def bfs10673(self):
    return 'option'

  def bfs10657(self):
    bfs11025 = super(bfs11021, self).bfs10657()
    return (bfs11025 + '/ancestor::select[1]')

  def bfs10641(self):
    bfs11026 = super(bfs11021, self).bfs10641()
    bfs11027 = []
    for bfs11031 in bfs11026:
      for bfs11030 in Select(bfs11031.unwrap()).all_selected_options:
        if self.bfs10630.text(bfs11030.text, self.search_text):
          bfs11027.append(bfs11031)
          break



    return bfs11027


class CheckBoxImpl(bfs10714):
  def is_enabled(self):
    return self.bfs10653()

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

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

  def bfs10726(self):
    return 'to_left_of'

  def bfs10730(self):
    return 'to_right_of'


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

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

  def bfs10726(self):
    return 'to_left_of'

  def bfs10730(self):
    return 'to_right_of'


class WindowImpl(bfs10606):
  def __init__(self, driver, title=None):
    super(WindowImpl, self).__init__(driver)
    self.bfs11032 = title

  def bfs10613(self):
    bfs11033 = []
    for handle in self.bfs10607.window_handles:
      window = WindowImpl.bfs11034(self.bfs10607, handle)
      if (self.bfs11032 is None):
        bfs11033.append((0, window))
      else:
        title = window.title
        if title.startswith(self.bfs11032):
          bfs11036 = (len(title) - len(self.bfs11032))
          bfs11033.append((bfs11036, window))



    bfs11036 = (lambda bfs11035: bfs11035[0])
    bfs11033.sort(key=bfs11036)
    for (bfs11036, window) in bfs11033:
      yield window


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

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

  class bfs11034(object):
    def __init__(self, driver, handle):
      self.driver = driver
      self.handle = handle
      self.bfs11037 = None

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


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


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




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

  def bfs10613(self):
    bfs11042 = self.bfs10607.switch_to.alert
    try:
      text = bfs11042.text
      if ((self.search_text is None) or text.startswith(self.search_text)):
        yield bfs11042

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


