text: from selenium import webdriver
  from selenium.webdriver.remote import webelement
  from selenium.webdriver.common.keys import Keys
  from selenium.webdriver.common.action_chains import ActionChains
  from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
  import time
  from .utils import log, error
  from threading import RLock
  from typing import Any
  from .settings import settings
  from fake_useragent import UserAgent
  
  
  def use_browser(org_func: Any):
      def wrapper(*args, **kwargs):
          browser = None
          for arg in args:
              if type(arg) is client:
                  browser = arg
                  break
  
          for _, value in kwargs.items():
              if type(value) is client:
                  browser = value
                  break
  
          # no custom browser given
          if browser is None:
              return org_func(*args, **kwargs)
  
          rv = None
          browser.use()
  
          try:
              rv = org_func(*args, **kwargs)
          except Exception as e:
              rv = None
              error(
                  "exception in function: {} exception: {}".format(
                      org_func.__name__, str(e)
                  )
              )
  
              log("reloading world.")
              url = browser.driver.current_url
              world = url.split("//")
              world = world[1]
              world = world.split(".")
              world = world[0]
  
              browser.get("https://{}.kingdoms.com".format(world))
          finally:
              browser.done()
  
              return rv
  
      return wrapper
  
  
  class client:
      def __init__(self, debug: bool = False) -> None:
          self.driver: webdriver = None
          self.delay = None
          self._headless: bool = False
          self.lock = RLock()
          self.proxy: bool = False
          self.debug: bool = debug
          self.current_session_path: str = settings.current_session_path
          pass
  
      def chrome(self, path: str, proxy: str = "") -> None:
          options = webdriver.ChromeOptions()
          if proxy != "":
              self.proxy = True
              options.add_argument("proxy-server={}".format(proxy))
  
          options.add_argument("window-size=1500,1200")
          options.add_argument("log-level=3")
  
          self.driver = webdriver.Chrome(path, chrome_options=options)
          self.set_config()
          self.save_session()
  
      def remote(self) -> None:
          if not self.debug:
              log("debug mode is turned off, can't reuse old session")
              return
  
          file = open(self.current_session_path, "r")
          content = file.read()
          lines = content.split(";")
          url = lines[0]
          session = lines[1]
  
          self.driver = webdriver.Remote(
              command_executor=url, desired_capabilities=DesiredCapabilities.CHROME
          )
          self.driver.session_id = session
  
          self.set_config()
  
      def headless(self, path: str, proxy: str = "") -> None:
          ua = UserAgent()
          userAgent = ua.random
          options = webdriver.ChromeOptions()
          options.add_argument("headless")
          options.add_argument("window-size=1500,1200")
          options.add_argument("no-sandbox")
          options.add_argument("disable-dev-shm-usage")
          options.add_argument("disable-gpu")
          options.add_argument("log-level=3")
          options.add_argument(f"user-agent={userAgent}")
  
          if proxy != "":
              self.proxy = True
              options.add_argument("proxy-server={}".format(proxy))
  
          self.driver = webdriver.Chrome(path, chrome_options=options)
          self.set_config()
          self._headless = True
  
      def set_config(self) -> None:
          # set timeout to find an element in seconds
          self.driver.implicitly_wait(5 * settings.browser_speed)
          # set page load timeout in seconds
          self.driver.set_page_load_timeout(15 + settings.browser_speed)
  
      # region locks
      def use(self) -> None:
          self.lock.acquire()
  
      def done(self) -> None:
          self.lock.release()
  
      # endregion
  
      # region browser function
      def get(self, page: str) -> None:
          self.driver.get(page)
  
      def find(self, xpath: str, wait: float = 0) -> webelement:
          # todo wait x seconds until presencd of element
          wait = wait * settings.browser_speed
          self.sleep(wait)
          return self.driver.find_element_by_xpath(xpath)
  
      def finds(self, xpath: str, wait: float = 0) -> webelement:
          # todo wait x seconds until presencd of element
          wait = wait * settings.browser_speed
          self.sleep(wait)
          return self.driver.find_elements_by_xpath(xpath)
  
      def sleep(self, seconds: float) -> None:
          seconds = seconds * settings.browser_speed
  
          # reduce sleep time if in headless mode
          if self._headless:
              seconds = seconds / 2
  
          # doubles the sleep time, proxys are normaly way slower
          if self.proxy:
              seconds = seconds * 2
  
          time.sleep(seconds)
  
      def click(self, element: webelement, wait: float = 0.5) -> None:
          ActionChains(self.driver).move_to_element(element).click().perform()
  
          wait = wait * settings.browser_speed
          self.sleep(wait)
  
      def click_v2(self, element: webelement, wait: float = 0.5) -> None:
          ActionChains(self.driver).move_to_element(element).click(element).perform()
  
          wait = wait * settings.browser_speed
          self.sleep(wait)
  
      def hover(self, element: webelement, wait: float = 0.5) -> None:
          ActionChains(self.driver).move_to_element(element).perform()
  
          wait = wait * settings.browser_speed
          self.sleep(wait)
  
      def scroll_down(self, element: webelement) -> None:
          element.send_keys(Keys.PAGE_DOWN)
  
      def refresh(self) -> None:
          self.driver.refresh()
  
      def current_url(self) -> str:
          return self.driver.current_url
  
      # endregion
  
      # region session
      def save_session(self) -> None:
          if not self.debug:
              return
  
          url = self.driver.command_executor._url
          session = self.driver.session_id
  
          filename = self.current_session_path
          semi = ";"
  
          content = url + semi + session
  
          try:
              file = open(filename, "w")
              file.write(content)
              file.close()
          except:
              log("Error saving Session")
  
      def write_source(self) -> None:
          file = open("./source.html", "w")
          file.write(self.driver.page_source)
          file.close()
  
      # endregion
  