from bfs.bfs10143.bfs10147 import LicensingError
from copy import copy
from decorator import decorator
from errno import ESRCH as bfs10455, EACCES as bfs10457
from helium.bfs10155.bfs10157 import bfs10160
from helium.bfs10155.bfs10171 import bfs10200
from helium.bfs10143.bfs10147 import bfs10201
from helium.bfs10143.bfs10221 import bfs10251, bfs10252
from helium.bfs10413 import bfs10436, bfs10420, bfs10437, bfs10445
from helium.bfs10063.bfs10450 import bfs10453
from helium.bfs10063.bfs10454 import bfs10456
from helium.bfs10063.system import bfs10163, bfs10164, bfs10162, bfs10167, bfs10165
from helium.bfs10063.bfs10146 import lower, predicate, bfs10154
from inspect import getargspec, ismethod, isfunction
from logging import getLogger
from os import access, X_OK
from os.path import exists
from selenium.common.exceptions import UnexpectedAlertPresentException, ElementNotVisibleException, MoveTargetOutOfBoundsException, WebDriverException, StaleElementReferenceException, NoAlertPresentException, NoSuchWindowException
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 re
import collections
@decorator
def bfs10466(bfs10104, self, *args, **bfs10461):
  driver = self.bfs10460()
  if (driver.bfs10426() and AlertImpl(driver).exists()):
    return bfs10104(self, *args, **bfs10461)

  bfs10462 = driver.window_handles[:]
  bfs10464 = bfs10104(self, *args, **bfs10461)
  if (not (driver.bfs10426() and AlertImpl(driver).exists())):
    bfs10463 = [bfs10465 for bfs10465 in driver.window_handles if (bfs10465 not in bfs10462) ]
    if bfs10463:
      driver.switch_to.window(bfs10463[0])


  return bfs10464

@decorator
def bfs10471(bfs10104, *args, **bfs10467):
  try:
    return bfs10104(*args, **bfs10467)
  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):
  bfs10470 = 'This operation requires a browser window. Please call one of the following functions first:\n * start_chrome()\n * start_firefox()\n * start_ie()\n * set_driver(...)'
  def __init__(self, bfs10472, bfs10473, bfs10474=None):
    self.bfs10472 = bfs10472
    self.license = bfs10473
    self.bfs10474 = bfs10474
    self.driver = None

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

  def bfs10506(self, url=None):
    bfs10477 = self.bfs10500()
    bfs10501 = ChromeOptions()
    bfs10501.add_argument('--test-type')
    bfs10503 = {'chrome_options': bfs10501}
    if exists(bfs10477):
      if (not access(bfs10477, X_OK)):
        try:
          bfs10456(bfs10477)
        except:
          raise RuntimeError(('The Chrome driver located at %s is not executable.' % bfs10477))


      getLogger(__name__).info('Using Chrome driver located at %s.', bfs10477)
      bfs10503['executable_path'] = bfs10477
    else:
      getLogger(__name__).warn('Could not find Chrome driver at expected location %s.', bfs10477)

    bfs10200()
    bfs10502 = Chrome(**bfs10503)
    atexit.register(self.bfs10504, bfs10502.service)
    return self.bfs10476(bfs10502, url)

  def bfs10500(self):
    if bfs10163():
      bfs10505 = 'chromedriver.exe'
    elif bfs10164():
      bfs10505 = ('chromedriver' + ('_x64' if bfs10167() else ''))
    else:
      assert bfs10162()
      bfs10505 = 'chromedriver'

    return self.bfs10472.bfs10507(bfs10165(), 'webdrivers', bfs10505)

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




  def bfs10515(self, url=None):
    bfs10511 = self.bfs10472.bfs10507('win', 'webdrivers', 'IEDriverServer.exe')
    capabilities = DesiredCapabilities.INTERNETEXPLORER.copy()
    capabilities['ignoreZoomSetting'] = True
    bfs10510 = {'capabilities': capabilities}
    if exists(bfs10511):
      getLogger(__name__).info('Using IE driver located at %s.', bfs10511)
      bfs10510['executable_path'] = bfs10511
    else:
      getLogger(__name__).warn('Could not find IE driver at expected location %s.', bfs10511)

    try:
      bfs10512 = Ie(**bfs10510)
    except WebDriverException as e:
      bfs10513 = e
      msg = e.msg
      if ('Protected Mode settings are not the same for all zones.' in msg):
        bfs10513 = WebDriverException('Error launching IE: Protected Mode settings are not the same for all zones. Please follow these steps: http://heliumhq.com/docs/internet_explorer#protected_mode')

      raise bfs10513

    atexit.register(self.bfs10504, bfs10512.iedriver)
    return self.bfs10476(bfs10512, url)

  def bfs10476(self, bfs10514, url=None):
    try:
      self.bfs10516(bfs10514)
    except LicensingError:
      bfs10514.quit()
      raise 

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

    return self.bfs10520()

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

    self.bfs10460().get(url)

  def bfs10516(self, driver):
    self.bfs10521(driver)
    self.driver = bfs10420(driver)

  def bfs10521(self, driver):
    try:
      self.license.bfs10523(bfs10251(self.bfs10474))
    except bfs10201:
      try:
        self.license.bfs10523(bfs10252(self.bfs10474, driver))
      except bfs10201:
        raise LicensingError('Unfortunately, Helium could not verify your license key. Please activate your internet connection and try again.')



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


  @bfs10466
  @bfs10471
  def bfs10526(self, text, into=None):
    if (into is not None):
      from helium.api import GUIElement
      if isinstance(into, GUIElement):
        into = into.bfs10522


    self.bfs10524(self.bfs10525, self.bfs10527, text, into=into)

  def bfs10525(self, text, into=None):
    if into:
      if isinstance(into, str):
        into = TextFieldImpl(self.bfs10460(), into)

      def bfs10531(bfs10530):
        if (hasattr(bfs10530, 'clear') and isinstance(bfs10530.clear, collections.Callable)):
          bfs10530.clear()

        bfs10530.send_keys(text)

      self.bfs10532(into, bfs10531)
    else:
      self.bfs10460().switch_to.active_element.send_keys(text)


  def bfs10527(self, text, into=None):
    if (into is None):
      into = AlertImpl(self.bfs10460())

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

    into.bfs10531(text)

  def bfs10524(self, bfs10534, bfs10533, *args, **bfs10535):
    driver = self.bfs10460()
    if (driver.bfs10427() or (not AlertImpl(driver).exists())):
      try:
        return bfs10534(*args, **bfs10535)
      except UnexpectedAlertPresentException:
        if (driver.bfs10427() and (not AlertImpl(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 bfs10533(*args, **bfs10535)

  @bfs10466
  @bfs10471
  def bfs10536(self, key):
    self.bfs10460().switch_to.active_element.send_keys(key)

  def bfs10541(self, element):
    self.bfs10540(element, (lambda bfs10537: bfs10537.click()), (lambda action_chains: action_chains.click()))

  def bfs10542(self, element):
    driver = self.bfs10460()
    self.bfs10540(element, (lambda bfs10543: driver.bfs10421().double_click(bfs10543).perform()), (lambda action_chains: action_chains.double_click()))

  def bfs10546(self, element):
    driver = self.bfs10460()
    self.bfs10540(element, (lambda bfs10544: driver.bfs10421().move_to_element(bfs10544).perform()), (lambda action_chains: action_chains))

  def bfs10547(self, element):
    driver = self.bfs10460()
    self.bfs10540(element, (lambda bfs10545: driver.bfs10421().context_click(bfs10545).perform()), (lambda action_chains: action_chains.context_click()))

  def bfs10551(self, element):
    driver = self.bfs10460()
    self.bfs10540(element, (lambda bfs10550: driver.bfs10421().click_and_hold(bfs10550).perform()), (lambda action_chains: action_chains.click_and_hold()))

  def bfs10554(self, element):
    bfs10552 = self.bfs10460()
    self.bfs10540(element, (lambda bfs10553: bfs10552.bfs10421().move_to_element(bfs10553).release().perform()), (lambda action_chains, bfs10555: action_chains.release(bfs10555)))

  @bfs10466
  @bfs10471
  def bfs10540(self, element, bfs10556, bfs10560):
    (element, offset) = self.bfs10557(element)
    driver = self.bfs10460()
    if (offset is not None):
      def bfs10421(bfs10561):
        action_chains = driver.bfs10421().move_to_element_with_offset(bfs10561, *offset)
        bfs10560(action_chains).perform()

    else:
      bfs10421 = bfs10556

    self.bfs10532(element, bfs10421)

  def bfs10557(self, bfs10530):
    from helium.api import HTMLElement, Point
    offset = None
    if isinstance(bfs10530, str):
      bfs10530 = bfs10562(self.bfs10460(), bfs10530)
    elif isinstance(bfs10530, HTMLElement):
      bfs10530 = bfs10530.bfs10522
    elif isinstance(bfs10530, Point):
      (bfs10530, offset) = self.bfs10563(bfs10530)

    return (bfs10530, offset)

  def bfs10563(self, bfs10565):
    driver = self.bfs10460()
    element = bfs10436(driver.execute_script(('return document.elementFromPoint(%r, %r);' % (bfs10565.x, bfs10565.y))))
    offset = (bfs10565 - (element.location.bfs10257, element.location.bfs10261))
    if ((offset == (0, 0)) and driver.bfs10427()):
      offset = (1, 1)

    return (element, offset)

  def bfs10572(self, element, to):
    with bfs10564(self) as bfs10566:
      (element, bfs10567) = self.bfs10557(element)
      self.bfs10532(element, bfs10566.bfs10571)
      (to, bfs10567) = self.bfs10557(to)
      self.bfs10532(to, bfs10566.bfs10570)


  @bfs10471
  def bfs10576(self, predicate):
    return [predicate.bfs10573(bfs10574) for bfs10574 in predicate.bfs10522.find_all()]

  def bfs10577(self, num_pixels):
    self.bfs10575(0, num_pixels)

  def bfs10600(self, num_pixels):
    self.bfs10575(0, (-num_pixels))

  def bfs10601(self, num_pixels):
    self.bfs10575(num_pixels, 0)

  def bfs10602(self, num_pixels):
    self.bfs10575((-num_pixels), 0)

  @bfs10471
  def bfs10575(self, bfs10603, bfs10605):
    self.bfs10460().execute_script('window.scrollBy(arguments[0], arguments[1]);', bfs10603, bfs10605)

  @bfs10466
  @bfs10471
  def bfs10606(self, combo_box, value):
    from helium.api import ComboBox
    if isinstance(combo_box, str):
      combo_box = ComboBoxImpl(self.bfs10460(), combo_box)
    elif isinstance(combo_box, ComboBox):
      combo_box = combo_box.bfs10522

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

    self.bfs10532(combo_box, bfs10604)

  def bfs10532(self, bfs10610, bfs10421):
    driver = self.bfs10460()
    if (hasattr(bfs10610, 'perform') and isinstance(bfs10610.perform, collections.Callable)):
      driver.bfs10417 = bfs10610.perform(bfs10421)
    else:
      if isinstance(bfs10610, WebElement):
        bfs10610 = bfs10436(bfs10610)

      bfs10421(bfs10610)
      driver.bfs10417 = bfs10610


  @bfs10471
  def bfs10614(self, file_path, to):
    (to, bfs10607) = self.bfs10557(to)
    drag_and_drop = bfs10611(self.bfs10460(), file_path)
    drag_and_drop.begin()
    try:
      drag_and_drop.bfs10612()
      self.bfs10532(to, (lambda bfs10613: drag_and_drop.bfs10615(bfs10613)))
    finally:
      drag_and_drop.end()


  @bfs10466
  @bfs10471
  def bfs10621(self, file_path, to=None):
    from helium.api import Point
    driver = self.bfs10460()
    if (to is None):
      to = bfs10616(driver)
    elif isinstance(to, str):
      to = bfs10616(driver, to)
    elif isinstance(to, Point):
      (to, bfs10607) = self.bfs10563(to)

    self.bfs10532(to, (lambda bfs10617: bfs10617.send_keys(file_path)))

  def bfs10624(self):
    self.bfs10524(self.bfs10620, self.bfs10622)

  def bfs10620(self):
    self.bfs10460().refresh()

  def bfs10622(self):
    AlertImpl(self.bfs10460()).accept()
    self.bfs10620()

  def bfs10631(self, condition_fn, timeout_secs=10, interval_secs=0.5):
    if ismethod(condition_fn):
      bfs10623 = (condition_fn.__self__ is not None)
      bfs10625 = getargspec(condition_fn).args
      bfs10626 = (len(bfs10625) - (1 if bfs10623 else 0))
    else:
      if (not isfunction(condition_fn)):
        condition_fn = condition_fn.__call__

      bfs10625 = getargspec(condition_fn).args
      bfs10626 = len(bfs10625)

    bfs10627 = (condition_fn if bfs10626 else (lambda driver: condition_fn()))
    wait = WebDriverWait(self.bfs10460().unwrap(), timeout_secs, poll_frequency=interval_secs)
    wait.until(bfs10627)

  @bfs10471
  def bfs10630(self, window):
    driver = self.bfs10460()
    from helium.api import Window
    if isinstance(window, str):
      window = WindowImpl(driver, window)
    elif isinstance(window, Window):
      window = window.bfs10522

    driver.switch_to.window(window.handle)

  def bfs10632(self):
    self.bfs10460().quit()
    self.driver = None

  @bfs10471
  def bfs10635(self, element):
    driver = self.bfs10460()
    from helium.api import HTMLElement, Text
    if isinstance(element, str):
      element = Text(element)

    if isinstance(element, HTMLElement):
      element = element.bfs10522

    try:
      element = element.first_occurrence
    except AttributeError:
      pass

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

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

  def bfs10460(self):
    if (not self.driver):
      raise RuntimeError(self.bfs10470)

    return self.driver


class bfs10564(object):
  def __init__(self, bfs10155):
    self.bfs10155 = bfs10155
    self.bfs10634 = None

  def __enter__(self):
    self.bfs10636("window.helium = {};window.helium.dragHelper = {    createEvent: function(type) {        var event = document.createEvent('CustomEvent');        event.initCustomEvent(type, true, true, null);        event.dataTransfer = {            data: {},            setData: function(type, val) {                this.data[type] = val;            },            getData: function(type) {                return this.data[type];            }        };        return event;    }};")
    return self

  def bfs10571(self, element):
    if self.bfs10637(element):
      self.bfs10634 = True
    else:
      self.bfs10155.bfs10551(element)


  def bfs10570(self, target):
    if self.bfs10634:
      self.bfs10641(target)
    else:
      self.bfs10155.bfs10554(target)


  def __exit__(self, *bfs10640):
    self.bfs10636('delete window.helium;')

  def bfs10637(self, bfs10642):
    return self.bfs10636("var source = arguments[0];function getDraggableParent(element) {    var previousParent = null;    while (element != null && element != previousParent) {        previousParent = element;        if ('draggable' in element) {            var draggable = element.draggable;            if (draggable === true)                return element;            if (typeof draggable == 'string'                     || draggable instanceof String)                if (draggable.toLowerCase() == 'true')                    return element;        }        element = element.parentNode;    }    return null;}var draggableParent = getDraggableParent(source);if (draggableParent == null)    return false;window.helium.dragHelper.draggedElement = draggableParent;var dragStart = window.helium.dragHelper.createEvent('dragstart');source.dispatchEvent(dragStart);window.helium.dragHelper.dataTransfer = dragStart.dataTransfer;return true;", bfs10642.unwrap())

  def bfs10641(self, bfs10643):
    self.bfs10636("var target = arguments[0];var drop = window.helium.dragHelper.createEvent('drop');drop.dataTransfer = window.helium.dragHelper.dataTransfer;target.dispatchEvent(drop);var dragEnd = window.helium.dragHelper.createEvent('dragend');dragEnd.dataTransfer = window.helium.dragHelper.dataTransfer;window.helium.dragHelper.draggedElement.dispatchEvent(dragEnd);", bfs10643.unwrap())

  def bfs10636(self, bfs10645, *args):
    return self.bfs10155.bfs10460().execute_script(bfs10645, *args)


class bfs10611(object):
  def __init__(self, driver, file_path):
    self.driver = driver
    self.file_path = file_path
    self.bfs10644 = None
    self.bfs10646 = None

  def begin(self):
    self.bfs10647()
    try:
      self.bfs10644.send_keys(self.file_path)
    except:
      self.end()
      raise 


  def bfs10647(self):
    self.bfs10644 = 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 bfs10612(self):
    self.bfs10650('dragenter', to='document.body')
    self.bfs10646 = self.bfs10651('dragover', 'document', interval_msecs=300)
    self.bfs10646.start()

  def bfs10650(self, bfs10653, to):
    (bfs10652, args) = self.bfs10654(bfs10653, to)
    self.driver.execute_script(bfs10652, *args)

  def bfs10651(self, bfs10656, to, interval_msecs):
    (bfs10655, args) = self.bfs10654(bfs10656, to)
    return bfs10657(self.driver, bfs10655, args, interval_msecs)

  def bfs10654(self, bfs10660, to):
    bfs10661 = "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):
      bfs10661 = bfs10661.replace('arguments[2]', to)
      args = (self.bfs10644, bfs10660)
    else:
      args = (self.bfs10644, bfs10660, to.unwrap())

    return (bfs10661, args)

  def bfs10615(self, target):
    self.bfs10646.stop()
    self.bfs10650('drop', to=target)

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

    self.bfs10644 = None


class bfs10657(object):
  def __init__(self, driver, bfs10662, args, interval_msecs):
    self.driver = driver
    self.bfs10662 = bfs10662
    self.args = args
    self.interval_msecs = interval_msecs
    self.bfs10663 = None

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

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


class bfs10664(object):
  def __init__(self, driver):
    self.bfs10666 = None
    self.bfs10670 = driver

  def find_all(self):
    if self.bfs10667():
      yield self
    else:
      for bfs10671 in self.bfs10672():
        yield self.bfs10674(bfs10671)



  def bfs10667(self):
    return (self.bfs10666 is not None)

  def bfs10672(self):
    raise NotImplementedError()

  def bfs10674(self, bfs10673):
    bfs10675 = copy(self)
    bfs10675.bfs10666 = bfs10673
    return bfs10675

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


  @property
  def first_occurrence(self):
    if (not self.bfs10667()):
      self.bfs10677()

    return self.bfs10666

  def bfs10677(self):
    self.perform((lambda bfs10676: None))

  def perform(self, bfs10421):
    from helium.api import Config
    bfs10700 = (time() + Config.implicit_wait_secs)
    bfs10702 = self.bfs10701(bfs10421)
    while ((bfs10702 is None) and (time() < bfs10700)):
      bfs10702 = self.bfs10701(bfs10421)

    if (bfs10702 is not None):
      return bfs10702

    raise LookupError()

  def bfs10701(self, bfs10421):
    for bfs10703 in self.find_all():
      bfs10705 = bfs10703.first_occurrence
      try:
        bfs10421(bfs10705)
      except Exception as e:
        if self.bfs10704(e):
          continue
        else:
          raise 

      else:
        self.bfs10666 = bfs10705
        return bfs10705



  def bfs10704(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)):
        getLogger(__name__).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 bfs10706(bfs10664):
  def __init__(self, driver, below=None, to_right_of=None, above=None, to_left_of=None):
    super(bfs10706, self).__init__(driver)
    self.below = self.bfs10707(below)
    self.to_right_of = self.bfs10707(to_right_of)
    self.above = self.bfs10707(above)
    self.to_left_of = self.bfs10707(to_left_of)
    self.bfs10711 = bfs10160()

  def bfs10707(self, element):
    if isinstance(element, str):
      return TextImpl(self.bfs10670, element)

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

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

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

  @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 bfs10672(self):
    self.bfs10710()
    self.bfs10670.switch_to.default_content()
    bfs10712 = self.bfs10714()
    try:
      for bfs10713 in bfs10437(self.bfs10670):
        for bfs10715 in self.bfs10717():
          if self.bfs10716(bfs10715, bfs10712):
            yield bfs10715



    except bfs10445:
      pass


  def bfs10710(self):
    window_handles = self.bfs10670.window_handles
    try:
      bfs10720 = self.bfs10670.current_window_handle
    except NoSuchWindowException:
      bfs10722 = True
    else:
      bfs10722 = (bfs10720 not in window_handles)

    if bfs10722:
      self.bfs10670.switch_to_window(window_handles[0])


  def bfs10714(self):
    bfs10702 = []
    if self.below:
      bfs10702.append(list(map((lambda bfs10721: bfs10721.location.is_above), self.below.bfs10672())))

    if self.to_right_of:
      bfs10702.append(list(map((lambda bfs10723: bfs10723.location.is_to_left_of), self.to_right_of.bfs10672())))

    if self.above:
      bfs10702.append(list(map((lambda bfs10724: bfs10724.location.is_below), self.above.bfs10672())))

    if self.to_left_of:
      bfs10702.append(list(map((lambda bfs10725: bfs10725.location.is_to_right_of), self.to_left_of.bfs10672())))

    return bfs10702

  def bfs10716(self, bfs10727, bfs10726):
    return (bfs10727.is_displayed() and self.bfs10730(bfs10727, bfs10726))

  def bfs10730(self, element, bfs10731):
    for bfs10733 in bfs10731:
      bfs10732 = False
      for bfs10734 in bfs10733:
        if bfs10734(element.location):
          bfs10732 = True
          break


      if (not bfs10732):
        return False


    return True

  def bfs10717(self):
    raise NotImplementedError()

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


class SImpl(bfs10706):
  def __init__(self, driver, bfs10736, **bfs10740):
    super(SImpl, self).__init__(driver, **bfs10740)
    self.bfs10736 = bfs10736

  def bfs10717(self):
    wrap = (lambda bfs10737: list(map(bfs10436, bfs10737)))
    if self.bfs10736.startswith('@'):
      return wrap(self.bfs10670.find_elements_by_name(self.bfs10736[1:]))

    if self.bfs10736.startswith('//'):
      return wrap(self.bfs10670.find_elements_by_xpath(self.bfs10736))

    return wrap(self.bfs10670.find_elements_by_css_selector(self.bfs10736))


class bfs10741(bfs10706):
  def bfs10717(self):
    bfs10742 = self.bfs10744()
    getLogger(__name__).debug('Looking for HTML element using xpath: %s.', bfs10742)
    return self.bfs10743(list(map(bfs10436, self.bfs10670.find_elements_by_xpath(bfs10742))))

  def bfs10743(self, bfs10745):
    bfs10746 = []
    for bfs10750 in bfs10745:
      try:
        key = self.bfs10747(bfs10750)
      except StaleElementReferenceException:
        pass
      else:
        bfs10746.append((key, bfs10750))


    bfs10751 = (lambda bfs10752: bfs10752[0])
    bfs10746.sort(key=bfs10751)
    bfs10754 = (lambda bfs10753: bfs10753[1])
    return list(map(bfs10754, bfs10746))

  def bfs10744(self):
    raise NotImplementedError()

  def bfs10747(self, web_element):
    return (self.bfs10670.bfs10422(web_element) + 1)


class bfs10755(bfs10741):
  def __init__(self, driver, text=None, **bfs10756):
    super(bfs10755, self).__init__(driver, **bfs10756)
    self.search_text = text

  def bfs10744(self):
    bfs10757 = (('//' + self.bfs10760()) + predicate(self.bfs10711.bfs10146('.', self.search_text)))
    return ('%s[not(self::script)][not(.%s)]' % (bfs10757, bfs10757))

  def bfs10760(self):
    return '*'


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

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

  def bfs10744(self):
    bfs10761 = ButtonImpl(self.bfs10670, self.search_text)
    bfs10763 = LinkImpl(self.bfs10670, self.search_text)
    bfs10765 = [self.bfs10764(), bfs10761.bfs10766(), bfs10763.bfs10744()]
    if (self.search_text and self.include_free_text):
      bfs10765.append(bfs10770(self.bfs10670, self.search_text).bfs10744())

    return ' | '.join(bfs10765)

  def bfs10764(self):
    if self.search_text:
      bfs10767 = super(TextImpl, self).bfs10744()
    else:
      bfs10771 = 'not(.//*[normalize-space(.)=normalize-space(self::*)])'
      bfs10767 = ('//*[text() and %s]' % bfs10771)

    return (bfs10767 + '[not(self::option)]')


class bfs10770(bfs10755):
  def bfs10760(self):
    return 'text()'

  def bfs10744(self):
    return (super(bfs10770, self).bfs10744() + '/..')


class LinkImpl(bfs10755):
  def bfs10760(self):
    return 'a'

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


class ListItemImpl(bfs10755):
  def bfs10760(self):
    return 'li'


class ButtonImpl(bfs10755):
  def bfs10760(self):
    return 'button'

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

  def bfs10744(self):
    bfs10773 = self.bfs10711.bfs10146('@aria-label', self.search_text)
    bfs10775 = self.bfs10711.bfs10146('.', self.search_text)
    bfs10774 = bfs10154(bfs10773, bfs10775)
    return ' | '.join([super(ButtonImpl, self).bfs10744(), self.bfs10766(), ("//*[@role='button']" + bfs10774), ('//button' + predicate(bfs10773))])

  def bfs10766(self):
    if self.search_text:
      bfs10776 = self.bfs10711.bfs10146('@value', self.search_text)
      bfs11000 = self.bfs10711.bfs10146('@label', self.search_text)
      bfs10777 = self.bfs10711.bfs10146('@aria-label', self.search_text)
      bfs11001 = self.bfs10711.bfs10146('@title', self.search_text)
      bfs11002 = bfs10154(bfs10776, bfs11000, bfs10777, bfs11001)
    else:
      bfs11002 = ''

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


class ImageImpl(bfs10741):
  def __init__(self, driver, alt, **bfs11004):
    super(ImageImpl, self).__init__(driver, **bfs11004)
    self.alt = alt

  def bfs10744(self):
    return ('//img' + predicate(self.bfs10711.bfs10146('@alt', self.alt)))


class bfs11003(bfs10706):
  bfs11005 = 1.5
  def __init__(self, driver, label=None, **bfs11007):
    super(bfs11003, self).__init__(driver, **bfs11007)
    self.label = label

  def bfs10717(self):
    if (not self.label):
      bfs11006 = self.bfs11010()
    else:
      bfs11012 = TextImpl(self.bfs10670, self.label, include_free_text=False).bfs10717()
      if bfs11012:
        bfs11006 = list(self.bfs11011(self.bfs11010(), bfs11012))
      else:
        bfs11006 = self.bfs11013()


    return sorted(bfs11006, key=self.bfs10670.bfs10422)

  def bfs11010(self, bfs11014=None):
    if (bfs11014 is None):
      bfs11014 = self.bfs10744()

    return list(map(bfs10436, self.bfs10670.find_elements_by_xpath(bfs11014)))

  def bfs11013(self):
    bfs11015 = [bfs10146.strip().lstrip('/') for bfs10146 in self.bfs10744().split('|')]
    bfs11016 = ('//text()' + predicate(self.bfs10711.bfs10146('.', self.label)))
    bfs10146 = ' | '.join([((((bfs11016 + '/%s::') + bfs11020) + '[1]') % ('preceding-sibling' if (('checkbox' in bfs11020) or ('radio' in bfs11020)) else 'following')) for bfs11020 in bfs11015])
    return self.bfs11010(bfs10146)

  def bfs10744(self):
    raise NotImplementedError()

  def bfs11017(self):
    return 'to_right_of'

  def bfs11021(self):
    return 'below'

  def bfs11011(self, bfs11023, bfs11022):
    for (label, bfs11024) in self.bfs11025(bfs11023, bfs11022):
      yield bfs11024
      bfs11022.remove(label)
      bfs11023.remove(bfs11024)

    bfs11026 = self.bfs11027(bfs11023, bfs11022)
    bfs11026 = self.bfs11031(bfs11026)
    self.bfs11030(bfs11026)
    for bfs11032 in list(bfs11026.values()):
      assert (len(bfs11032) <= 1)
      if bfs11032:
        yield next(iter(bfs11032))



  def bfs11025(self, bfs11033, bfs11034):
    for label in bfs11034:
      if (label.tag_name == 'label'):
        bfs11036 = label.get_attribute('for')
        if bfs11036:
          for bfs11035 in bfs11033:
            bfs11037 = bfs11035.get_attribute('id')
            if (bfs11037.lower() == bfs11036.lower()):
              yield (label, bfs11035)






  def bfs11027(self, bfs11040, bfs11042):
    bfs11041 = {}
    for label in bfs11042:
      for bfs11043 in bfs11040:
        if self.bfs11044(bfs11043, label):
          if (label not in bfs11041):
            bfs11041[label] = set()

          bfs11041[label].add(bfs11043)



    return bfs11041

  def bfs11044(self, bfs11045, label):
    if bfs11045.location.bfs10323(label.location):
      return True

    bfs11047 = self.bfs11017()
    bfs11046 = self.bfs11021()
    return ((label.location.bfs10351(bfs11045.location) <= 150) and (bfs11045.location.bfs10340(bfs11047, label.location) or bfs11045.location.bfs10340(bfs11046, label.location)))

  def bfs11031(self, bfs11050):
    bfs11051 = bfs10453(bfs11050)
    self.bfs11030(bfs11051)
    return bfs10453(bfs11051)

  def bfs11030(self, bfs11053):
    for (bfs11052, bfs11054) in list(bfs11053.items()):
      if bfs11054:
        bfs11053[bfs11052] = set([self.bfs11056(bfs11052, bfs11054)])



  def bfs11056(self, bfs11055, bfs11057):
    bfs11061 = iter(bfs11057)
    bfs11060 = next(bfs11061)
    bfs11062 = self.bfs11064(bfs11060, bfs11055)
    for element in bfs11061:
      bfs11063 = self.bfs11064(element, bfs11055)
      if (bfs11063 < bfs11062):
        bfs11060 = element
        bfs11062 = bfs11063


    return bfs11060

  def bfs11064(self, bfs11065, bfs11067):
    bfs11066 = bfs11065.location
    bfs11070 = bfs11067.location
    if bfs11066.bfs10340(self.bfs11021(), bfs11070):
      bfs11071 = self.bfs11005
    else:
      bfs11071 = 1

    return (bfs11071 * bfs11066.bfs10351(bfs11070))


class bfs11073(bfs10706):
  def __init__(self, driver, *args, **bfs10106):
    super(bfs11073, self).__init__(driver, **bfs10106)
    self.args = ([driver] + list(args))
    self.bfs10106 = bfs10106
    self.bfs11072 = None

  @property
  def bfs11074(self):
    if (self.bfs11072 is None):
      self.bfs10677()

    return self.bfs11072

  def find_all(self):
    bfs11075 = []
    for element in self.bfs11077():
      for bfs11076 in element.find_all():
        if (self.bfs11072 is None):
          self.bfs11072 = element

        if (bfs11076 not in bfs11075):
          yield bfs11076
          bfs11075.append(bfs11076)




  def bfs11077(self):
    for bfs11100 in self.bfs11102():
      yield bfs11100(*self.args, **self.bfs10106)


  def bfs11102(self):
    raise NotImplementedError()


class bfs10562(bfs11073):
  def __init__(self, driver, text, **bfs11101):
    super(bfs10562, self).__init__(driver, text, **bfs11101)

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


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

  def bfs11102(self):
    return [bfs11104, bfs11105, bfs11107]

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

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

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


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

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

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

  def bfs10744(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 bfs11107(bfs11003):
  @property
  def value(self):
    return self.first_occurrence.text

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

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

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


class bfs11104(bfs10741):
  def __init__(self, driver, label, **bfs11106):
    super(bfs11104, self).__init__(driver, **bfs11106)
    self.label = label

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

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

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

  def bfs10744(self):
    return ('(%s)%s' % (bfs11105(self.label).bfs10744(), predicate(self.bfs10711.bfs10146('@placeholder', self.label))))


class bfs10616(bfs11003):
  def bfs10744(self):
    return "//input[@type='file']"


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

  def bfs11102(self):
    return [bfs11112, bfs11111]

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

  @property
  def value(self):
    bfs11113 = self.bfs11115.first_selected_option
    if bfs11113:
      return bfs11113.text

    return None

  @property
  def options(self):
    return [bfs11114.text for bfs11114 in self.bfs11115.options]

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


class bfs11112(bfs11003):
  def bfs10744(self):
    return '//select | //input[@list]'


class bfs11111(bfs10755):
  def bfs10760(self):
    return 'option'

  def bfs10744(self):
    bfs11116 = super(bfs11111, self).bfs10744()
    return (bfs11116 + '/ancestor::select[1]')

  def bfs10717(self):
    bfs11117 = super(bfs11111, self).bfs10717()
    bfs11121 = []
    for bfs11120 in bfs11117:
      for bfs11122 in Select(bfs11120.unwrap()).all_selected_options:
        if self.bfs10711.text(bfs11122.text, self.search_text):
          bfs11121.append(bfs11120)
          break



    return bfs11121


class CheckBoxImpl(bfs11003):
  def is_enabled(self):
    return self.bfs10735()

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

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

  def bfs11017(self):
    return 'to_left_of'

  def bfs11021(self):
    return 'to_right_of'


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

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

  def bfs11017(self):
    return 'to_left_of'

  def bfs11021(self):
    return 'to_right_of'


class WindowImpl(bfs10664):
  def __init__(self, driver, title=None):
    super(WindowImpl, self).__init__(driver)
    self.bfs11124 = title

  def bfs10672(self):
    bfs11123 = []
    for handle in self.bfs10670.window_handles:
      window = WindowImpl.bfs11125(self.bfs10670, handle)
      if (self.bfs11124 is None):
        bfs11123.append((0, window))
      else:
        title = window.title
        if title.startswith(self.bfs11124):
          bfs11127 = (len(title) - len(self.bfs11124))
          bfs11123.append((bfs11127, window))



    bfs11127 = (lambda bfs11126: bfs11126[0])
    bfs11123.sort(key=bfs11127)
    for (bfs11127, window) in bfs11123:
      yield window


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

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

  class bfs11125(object):
    def __init__(self, driver, handle):
      self.driver = driver
      self.handle = handle
      self.bfs11130 = None

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


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


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




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

  def bfs10672(self):
    bfs11132 = self.bfs10670.switch_to.alert
    try:
      text = bfs11132.text
      if ((self.search_text is None) or text.startswith(self.search_text)):
        yield bfs11132

    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)):
        getLogger(__name__).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 bfs10531(self, text):
    self.first_occurrence.send_keys(text)


