from yta_general_utils.tmp_processor import create_tmp_filename
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.remote.webelement import WebElement

import time
import os
import pyautogui
import glob
import shutil

PROJECT_ABSOLUTE_PATH = os.getenv('PROJECT_ABSOLUTE_PATH')
TOUSE_ABSOLUTE_PATH = os.getenv('TOUSE_ABSOLUTE_PATH') 

class ChromeScrapper:
    gui = True
    ad_blocker = True
    disable_popup_and_cookies = True
    additional_options = []
    max_page_load_waiting_time = 10

    def __init__(self, gui: bool = False, ad_blocker: bool = True, disable_popup_and_cookies: bool = True, additional_options = [], max_page_load_waiting_time: float = 10):
        # TODO: Make more customizable accepting ad_blocker extension name
        # and stuff like that
        self.gui = gui
        self.ad_blocker = ad_blocker
        self.disable_popup_and_cookies = disable_popup_and_cookies
        self.additional_options = additional_options
        self.max_page_load_waiting_time = max_page_load_waiting_time

    def __init_options(self):
        """
        Initializes the Google Chrome options and returns them.
        """
        if not self.options:
            # TODO: This must be dynamic and/or given by user
            CHROME_EXTENSIONS_ABSOLUTEPATH = 'C:/Users/dania/AppData/Local/Google/Chrome/User Data/Profile 2/Extensions/'
            # TODO: Extensions versions are updated, so check below line
            AD_BLOCK_ABSOLUTEPATH = CHROME_EXTENSIONS_ABSOLUTEPATH + 'cjpalhdlnbpafiamejdnhcphjbkeiagm/1.59.0_0'
            # TODO: What if 'import undetected_chromedriver.v2 as uc'? Try it

            options = Options()
            
            option_arguments = ['--start-maximized']

            if len(self.additional_options) > 0:
                for additional_option in self.additional_options:
                    option_arguments.append(additional_option)

            if not self.gui:
                option_arguments.append('--headless=new')

            if self.ad_blocker:
                # This loads the ad block 'uBlock' extension that is installed in my pc
                option_arguments.append('load-extension=' + AD_BLOCK_ABSOLUTEPATH)
            
            # Load user profile
            option_arguments.append('user-data-dir=C:/Users/dania/AppData/Local/Google/Chrome/User Data/Profile 2')

            for argument in option_arguments:
                options.add_argument(argument)

            if self.disable_popups_and_cookies:
                # TODO: Separate this into specific options, not all together. One is for cookies,
                # another one is for popups... Separate them, please
                # This disables popups, cookies and that stuff
                options.add_experimental_option('prefs', {
                    'excludeSwitches': ['enable-automation', 'load-extension', 'disable-popup-blocking'],
                    'profile.default_content_setting_values.automatic_downloads': 1,
                    'profile.default_content_setting_values.media_stream_mic': 1
                })

            self.options = options

        return self.options
    
    def __init_driver(self):
        """
        Initializes the Google Chrome driver and returns it.
        """
        if not self.driver:
            self.driver = webdriver.Chrome(options = self.__init_options())

        return self.driver
    
    def go_to_web_and_wait_util_loaded(self, url: str):
        """
        Navigates to the provided 'url' and checks continuously
        if the page has been loaded or not. It will wait for
        'max_page_load_waiting_time' seconds set when the
        ChromeScrapper object was created.

        This method will return True in the moment the page is 
        loaded.
        """
        if not url:
            raise Exception('No "url" provided.')
    
        CHECK_TIME = 0.25

        try:
            self.__init_driver()
            self.driver.get(url)

            page_state = 'loading'
            cont = 0
            while page_state != 'complete' and cont < (self.max_page_load_waiting_time / CHECK_TIME):
                time.sleep(CHECK_TIME)
                page_state = self.driver.execute_script('return document.readyState;')
                cont += 1

            if page_state == 'loading':
                return False
            
            return True

        except:
            self.driver.close()
            self.driver = None

    def press_ctrl_letter(self, letter: str = 'c'):
        """
        Holds the Ctrl key down, presses the provided 'letter' and 
        releases the Ctrl key. This is useful for Ctrl+C, Ctrl+V
        combinations.
        """
        # TODO: Check if letter is valid
        if not letter:
            raise Exception('No "letter" provided.')
        
        letter = letter[0]

        ActionChains(self.driver).key_down(Keys.CONTROL).send_keys(letter).key_up(Keys.CONTROL).perform()

    def press_ctrl_letter_on_element(self, letter: str, element: WebElement):
        """
        Presses the Ctrl + provided 'letter' in the also provided
        'element'. Useful to paste text into text elements.
        """
        if not letter:
            raise Exception('No "letter" provided.')
        
        if not element:
            raise Exception('No "element" provided.')
        
        letter = letter[0]

        element.send_keys(Keys.CONTROL, letter)

    def press_ctrl_c(self):
        self.press_ctrl_letter('c')

    def press_ctrl_c_on_element(self, element: WebElement):
        self.press_ctrl_letter_on_element('c', element)

    def press_ctrl_x(self):
        self.press_ctrl_letter('x')

    def press_ctrl_x_on_element(self, element: WebElement):
        self.press_ctrl_letter_on_element('x', element)

    def press_ctrl_v(self):
        self.press_ctrl_letter('v')

    def press_ctrl_v_on_element(self, element: WebElement):
        self.press_ctrl_letter_on_element('v', element)

    def find_element_by_text(self, element_type: str, text: str):
        """
        This method uses the 'By.XPATH' finding elements method
        with the '//element_type[contains(text(), 'text')]' 
        structure to find the element, useful for buttons that 
        have 'Save' text or things similar.

        You can use 'element_type' = 'button' and 'text' =
        'Guardar' to find the elements like this one:
        <button>Guardar</button>

        You can also use the wildcard '*'  to find any type of
        element with the specific provided 'text'.

        This method returns the first found WebElement if 
        existing or None if not found.
        """
        elements = self.find_elements_by_text(element_type, text)
        
        if len(elements) > 0:
            return elements[0]
        
        return None
    
    def find_elements_by_text(self, element_type: str, text: str):
        """
        This method uses the 'By.XPATH' finding elements method
        with the '//element_type[contains(text(), 'text')]' 
        structure to find the element, useful for buttons that 
        have 'Save' text or things similar.

        You can use 'element_type' = 'button' and 'text' =
        'Guardar' to find the elements like this one:
        <button>Guardar</button>

        You can also use the wildcard '*'  to find any type of
        element with the specific provided 'text'.

        This method returns an array with all the found elements
        or empty if not found.
        """
        if not element_type:
            raise Exception('No "element_type" provided.')
        
        if not text:
            raise Exception('No "text" provided.')

        return self.driver.find_elements(By.XPATH, "//" + element_type + "[contains(text(), '" + text + "')]")
    
    def find_element_by_class(self, element_type: str, class_str: str):
        """
        This method uses the 'By.XPATH' finding elements method
        with the '//element_type[contains(@class, 'class_str')]' 
        structure to find the element, useful for divs with a
        specific class or similar.

        You can use 'element_type' = 'div' and 'class_str' =
        'container-xl' to find the elements like this one:
        <div class='container-xl'>content</div>

        You can also use the wildcard '*'  to find any type of
        element with the specific provided 'class_str'.

        This method returns the first found WebElement if 
        existing or None if not found.
        """
        elements = self.find_elements_by_class(element_type, class_str)
        
        if len(elements) > 0:
            return elements[0]
        
        return None

    def find_elements_by_class(self, element_type: str, class_str: str):
        """
        This method uses the 'By.XPATH' finding elements method
        with the '//element_type[contains(@class, 'class_str')]' 
        structure to find the element, useful for divs with a
        specific class or similar.

        You can use 'element_type' = 'div' and 'class_str' =
        'container-xl' to find the elements like this one:
        <div class='container-xl'>content</div>

        You can also use the wildcard '*'  to find any type of
        element with the specific provided 'class_str'.

        This method returns an array with all the found elements
        or empty if not found.
        """
        if not element_type:
            raise Exception('No "element_type" provided.')
        
        if not class_str:
            raise Exception('No "class_str" provided.')

        return self.driver.find_elements(By.XPATH, "//" + element_type + "[contains(@class, '" + class_str + "')]")

    def find_element_by_custom_tag(self, element_type: str, custom_tag: str, custom_tag_value: str):
        """
        This method uses the 'By.XPATH' finding elements method
        with the '//element_type[@custom-tag='custom_value')]' 
        structure to find the element, useful for divs with a
        specific tag or similar.

        You can use the wildcard '*'  to find any type of
        element with the specific provided 'custom_tag'.

        This method returns the first found WebElement if 
        existing or None if not found.
        """
        elements = self.find_elements_by_custom_tag(element_type, custom_tag, custom_tag_value)
        
        if len(elements) > 0:
            return elements[0]
        
        return None

    def find_elements_by_custom_tag(self, element_type: str, custom_tag: str, custom_tag_value: str):
        """
        This method uses the 'By.XPATH' finding elements method
        with the '//element_type[@custom-tag='custom_value')]' 
        structure to find the element, useful for divs with a
        specific tag or similar.

        You can use the wildcard '*'  to find any type of
        element with the specific provided 'custom_tag'.

        This method returns an array with all the found elements
        or empty if not found.
        """
        if not element_type:
            raise Exception('No "element_type" provided.')
        
        if not custom_tag:
            raise Exception('No "class_str" provided.')
        
        # @custom-tag or @custom-tag='something'
        tag = '@' + custom_tag
        if custom_tag_value:
            tag += "='" + custom_tag_value + "'"

        # driver.find_elements_by_xpath('//*[@data-testid="number-input"]')
        return self.driver.find_elements(By.XPATH, "//" + element_type + "[@" + tag + "')]")
    
    def get_current_page_y_offset(self):
        """
        Returns the current page Y axis offset by executing the
        'return window.pageYOffset' script. This means the amount
        of pixels moved from the origin (top). An offset of 50 
        pixels means that has been a scroll down of 50 pixels.
        The minimum value is 0 when on top of the web page.
        """
        return self.driver.execute_script("return window.pageYOffset")

    def scroll_down(self, pixels: int):
        # TODO: Check if 'pixels' is valid

        pixels = abs(pixels)
        pixels += self.get_current_page_y_offset()
        self.driver.execute_script('window.scrollTo(0, ' + pixels + ')')

    def scroll_up(self, pixels: int):
        # TODO: Check if 'pixels' is valid

        pixels = abs(pixels)
        current_y = self.get_current_page_y_offset()
        if current_y - pixels > 0:
            pixels = current_y - pixels
        else:
            pixels = 0
        self.driver.execute_script('window.scrollTo(0, ' + pixels + ')')

    def get_page_height(self):
        """
        Returns the current page height by executing the
        'return document.body.scrollHeight' script. This means
        the amount of pixels from top to bottom.
        """
        return self.driver.execute_script("return document.body.scrollHeight")

    def screenshot(self, output_filename: str = None):
        """
        Takes a screenshot of the whole page and returns the 
        it as binary data if no 'output_filename' provided. 
        If 'output_filename' is provided, it will be stored 
        locally with that name.
        """
        # TODO: Make this method return the image as binary
        # data always and store if 'output_filename' is 
        # provided, but you cannot do the 'save_screenshot'
        # twice because the webpage can change in the time
        # elapsed between both screenshots.
        if not output_filename:
            return self.driver.get_screenshot_as_png()
        
        self.driver.save_screenshot(output_filename)

        return output_filename
    
    def screenshot_element(self, element: WebElement, output_filename: str = None):
        """
        Takes a screenshot of the provided 'element', that
        means that only the area occupied by that element
        is shown in the screenshot, and returns it as 
        binary data if no 'output_filename' provided or
        will be stored locally if provided.

        Any element of the web page that is over the 
        element will appear in the screenshot blocking it.
        """
        # TODO: Make this method return the image as binary
        # data always and store if 'output_filename' is 
        # provided, but you cannot do the 'save_screenshot'
        # twice because the webpage can change in the time
        # elapsed between both screenshots.
        if not element:
            raise Exception('No "element" provided.')
        
        if not output_filename:
            return element.screenshot_as_png()
        
        element.screenshot(output_filename)

        return output_filename

    def screenshot_web_page(self, url: str):
        """
        This method will take screenshots of the whole
        web page. It will do in the current page if
        no 'url' is provided, or will navigate to the
        provided 'url' and do it in that one.
        """
        if url:
            self.go_to_web_and_wait_util_loaded(url)

        # TODO: Screenshot the whole page
        FPS = 60
        # Maybe this should be a parameter
        # TODO: We want to make screenshots for a video
        # so depending on 'duration' it will be slower
        # or more dynamic. This method need testing
        duration = 5

        # TODO: Maybe we want to scroll more, or maybe
        # we should pass this a parameter to make it
        # more customizable
        page_height = self.get_page_height()
        if page_height > 1000:
            page_height = 1000

        screenshots = []
        number_of_screenshots = int(duration * FPS)

        # TODO: How much should we scroll?
        new_height = 0
        for i in range(number_of_screenshots):
            screenshots.append(self.driver.get_screenshot_as_png)
            height = self.get_current_page_y_offset()
            new_height += page_height / number_of_screenshots
            # We scroll down the difference
            self.scroll_down(new_height - height)

        # TODO: What if we end before



# TODO: Remove all this below when all refactored
    

def go_to_and_wait_loaded(driver, url):
    """
    Navigates to the provided 'url', using the provided 'driver', and waits until
    the page is loaded (by readyState method). If it is loaded, it returns True.
    If not, it returns False.

    This method will wait for 10 seconds maximum.
    """
    try:
        driver.get(url)

        page_state = 'loading'
        cont = 0
        while page_state != 'complete' and cont < 20:
            time.sleep(0.5)
            page_state = driver.execute_script('return document.readyState;')
            cont += 1

        if page_state == 'loading':
            return False
        
        return True
    except:
        driver.close()

def start_chrome(gui = False, ad_blocker = True, disable_popups_and_cookies = True, additional_options = []):
    """
    Starts the chrome driver with the local configuration and returns it. If 'gui' is True,
    it will show the Chrome working.

    Additional options must be simple strings. Cookies must be objects with .name and .value.
    """
    try:
        CHROME_EXTENSIONS_ABSOLUTEPATH = 'C:/Users/dania/AppData/Local/Google/Chrome/User Data/Profile 2/Extensions/'
        # TODO: Extensions versions are updated, so check below line
        AD_BLOCK_ABSOLUTEPATH = CHROME_EXTENSIONS_ABSOLUTEPATH + 'cjpalhdlnbpafiamejdnhcphjbkeiagm/1.59.0_0'

        # TODO: What if 'import undetected_chromedriver.v2 as uc'? Try it

        options = Options()
        
        option_arguments = ['--start-maximized']

        if len(additional_options) > 0:
            for additional_option in additional_options:
                option_arguments.append(additional_option)

        if not gui:
            option_arguments.append('--headless=new')

        if ad_blocker:
            # This loads the ad block 'uBlock' extension that is installed in my pc
            option_arguments.append('load-extension=' + AD_BLOCK_ABSOLUTEPATH)
        
        # Load user profile
        option_arguments.append('user-data-dir=C:/Users/dania/AppData/Local/Google/Chrome/User Data/Profile 2')

        for argument in option_arguments:
            options.add_argument(argument)

        if disable_popups_and_cookies:
            # TODO: Separate this into specific options, not all together. One is for cookies,
            # another one is for popups... Separate them, please
            # This disables popups, cookies and that stuff
            options.add_experimental_option('prefs', {
                'excludeSwitches': ['enable-automation', 'load-extension', 'disable-popup-blocking'],
                'profile.default_content_setting_values.automatic_downloads': 1,
                'profile.default_content_setting_values.media_stream_mic': 1
                })

        driver = webdriver.Chrome(options = options)

        return driver
    except:
        driver.close()

def download_fake_call_image(name, output_filename):
    # TODO: Move this to the faker
    URL = 'https://prankshit.com/fake-iphone-call.php'

    try:
        driver = start_chrome()
        go_to_and_wait_loaded(driver, URL)

        inputs = driver.find_elements(By.TAG_NAME, 'input')
        name_textarea = driver.find_element(By.TAG_NAME, 'textarea')

        #operator_input = inputs[4]
        #hour_input = inputs[5]

        name_textarea.clear()
        name_textarea.send_keys(name)

        image = driver.find_element(By.XPATH, '//div[contains(@class, "modal-content tiktok-body")]')
        image.screenshot(output_filename)
    finally:
        driver.close()

# Other fake generators (https://fakeinfo.net/fake-twitter-chat-generator) ad (https://prankshit.com/fake-whatsapp-chat-generator.php)
def download_discord_message_image(text, output_filename):
    URL = 'https://message.style/app/editor'

    try:
        driver = start_chrome()
        go_to_and_wait_loaded(driver, URL)
        
        time.sleep(3)

        clear_embed_button = driver.find_element(By.XPATH, "//button[contains(text(), 'Clear Embeds')]")
        clear_embed_button.click()

        time.sleep(3)

        input_elements = driver.find_elements(By.TAG_NAME, 'input')
        username_input = input_elements[3]
        avatar_url_input = input_elements[4]

        username_input.clear()
        username_input.send_keys('botsito')

        avatar_url_input.clear()
        avatar_url_input.send_keys('https://cdn.pixabay.com/photo/2016/11/18/23/38/child-1837375_640.png')

        textarea_input = driver.find_element(By.TAG_NAME, 'textarea')
        textarea_input.clear()
        textarea_input.send_keys(text)

        time.sleep(3)

        # get element div class='discord-message'
        discord_message = driver.find_element(By.XPATH, "//div[contains(@class, 'discord-message')]")
        discord_message.screenshot(output_filename)
    finally:
        driver.close()


def navigate_to_and_screenshot(url, duration):
    """
    Browses the website 'url' and takes screenshots  while scrolling down. This method
    takes 30 screenshots per second.

    Returns the array of screenshot filenames stored locally.
    """
    try:
        FPS = 30

        driver = start_chrome()
        go_to_and_wait_loaded(driver, url)
        
        page_height = 0
        page_height = driver.execute_script("return document.body.scrollHeight")
        print(page_height)
        # We force it to 1000 if bigger
        if page_height > 1000:
            page_height = 1000

        screenshot_filenames = []
        number_of_screenshots = int(duration * FPS)

        # How much should we scroll?
        new_height = 0
        for i in range(number_of_screenshots):
            screenshot_filename = 'wip/screenshot_' + str(i) + '.png'
            driver.save_screenshot(screenshot_filename)
            screenshot_filenames.append(screenshot_filename)
            height = driver.execute_script("return window.pageYOffset")
            new_height += page_height / number_of_screenshots
            driver.execute_script('window.scrollTo(' + str(height) + ', ' + str(new_height) + ')')

        driver.execute_script("window.close();")
    finally:
        driver.close()

    # TODO: These screenshots are not 1920x1080, so crop them from center to sides
    return screenshot_filenames
    

def test_download_piano_music():
    # TODO: End this, to make it download music generated by this AI
    try:
        options = Options()
        #option_arguments = ['--start-maximized', '--headless=new']
        option_arguments = ['--start-maximized']
        for argument in option_arguments:
            options.add_argument(argument)

        driver = webdriver.Chrome(options = options)
        driver.get('https://huggingface.co/spaces/mrfakename/rwkv-music')
        wait = WebDriverWait(driver, 30)
        download_button_element = wait.until(EC.visibility_of_element_located((By.XPATH, '//*[@data-testid=\"checkbox\"]')))

        time.sleep(5)
        actions = ActionChains(driver)
        for i in range(11):
            actions.send_keys(Keys.TAB)
        actions.perform()
        actions.send_keys(Keys.SPACE)
        actions.perform()

        input_number_element = driver.find_elements_by_xpath('//*[@data-testid="number-input"]')[0]
        input_number_element.send_keys(14286)

        actions = ActionChains(driver)
        actions.send_keys(Keys.TAB)
        actions.perform()

        time.sleep(1)

        driver.execute_script('window.scrollTo(0, 1000)')

        time.sleep(4)

        download_button_element = wait.until(EC.visibility_of_element_located((By.XPATH, '//*[@title=\"Download\"]')))
        #download_button_element = driver.find_elements_by_xpath('//*[@title="Download"]')[0]
        download_button_element.click()

    finally:
        driver.close()


def goto_and_scroll(url):
    # Intersting options: https://github.com/ultrafunkamsterdam/undetected-chromedriver/issues/1726
    # Also this: https://stackoverflow.com/questions/19211006/how-to-enable-cookies-in-chromedriver-with-webdriver
    # What about this: options.AddUserProfilePreference("profile.cookie_controls_mode", 0);
    try:
        options = Options()
        option_arguments = ['--start-maximized', '--disabled-infobars', '--disable-blink-features=AutomationControlled', '--disable-animations', '--no-sandbox', '--disable-setuid-sandbox']
        # options.AddUserProfilePreference("profile.cookie_controls_mode", 0);
        for argument in option_arguments:
            options.add_argument(argument)

        """
        experimental_option_arguments = [{
            'option': 'excludeSwitches',
            'value': 'enable-automation'
        }]
        if len(experimental_option_arguments) > 0:
            options.add_experimental_option(experimental_option_arguments)
        """
        # Remove this line below for debug
        #options.add_argument("--headless=new") # for Chrome >= 109
        print('@@@@@@@@@@@@@')
        driver = webdriver.Chrome(options = options)
        print('@@@@@@@@@@@@@')
        driver.get(url)
        print('here i am')

        # Accept cookies

        #driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
        time.sleep(4)

        driver.execute_script('window.scrollTo(0, 200)')
        time.sleep(4)
    except Exception as e:
        print(e)
    finally:
        driver.close()

def get_redicted_url(url, expected_url = None, wait_time = 5):
    """
    Navigates to the provided url and waits for a redirection. This method will wait
    until the 'expected_url' is contained in the new url (if 'expected_url' parameter
    is provided), or waits 'wait_time' seonds to return the current_url after that.
    """
    redirected_url = ''

    try:
        options = Options()
        options.add_argument("--start-maximized")
        # Remove this line below for debug
        options.add_argument("--headless=new") # for Chrome >= 109
        driver = webdriver.Chrome(options = options)
        driver.get(url)

        wait = WebDriverWait(driver, 10)

        if not expected_url:
            time.sleep(wait_time)
        else:
            wait.until(EC.url_contains(expected_url))

        redirected_url = driver.current_url
    finally:
        driver.close()

    return redirected_url


def get_youtube_summary(video_id):
    """
    Searchs into 'summarize.tech' web to obtain the summary of the video with the 
    provided 'video_id'. This method returns the summary in English, as it is 
    provided by that website.
    """
    url = 'https://www.summarize.tech/www.youtube.com/watch?v=' + video_id

    try:
        options = Options()
        options.add_argument("--start-maximized")
        # Remove this line below for debug
        options.add_argument("--headless=new") # for Chrome >= 109
        driver = webdriver.Chrome(options = options)
        driver.get(url)

        summary = driver.find_element_by_tag_name('section').find_element_by_tag_name('p').get_attribute('innerText')
    finally:
        driver.close()

    return summary

def google_translate(text, input_language = 'en', output_language = 'es'):
    url = 'https://translate.google.com/?hl=es'
    """
    https://translate.google.com/?hl=es&sl=en&tl=es&text=Aporta%20una%20unidad%20de%20traducci%C3%B3n%20(segmento%20y%20traducci%C3%B3n)%20en%20alg%C3%BAn%20par%20de%20idiomas%20a%20MyMemory.%0ASin%20especificar%20ning%C3%BAn%20par%C3%A1metro%20clave%2C%20la%20contribuci%C3%B3n%20est%C3%A1%20disponible%20para%20todos%20(%C2%A1Gracias!).&op=translate

    https://translate.google.com/?hl=es&tab=TT&sl=en&tl=es&op=translate

    https://translate.google.com/?hl=es&tab=TT&sl=en&tl=es&text=La%20%C3%BAnica%20forma%20de%20saberlo%20es%20lo%20que%20t%C3%BA%20digas&op=translate
    """

    url = 'https://translate.google.com/?hl=' + output_language + '&tab=TT&sl=' + input_language + '&tl=' + output_language + '&text=' + text + '&op=translate'

    translation = ''

    try:
        options = Options()
        options.add_argument("--start-maximized")
        # Comment this line below for debug (enables GUI)
        options.add_argument("--headless=new") # for Chrome >= 109
        driver = webdriver.Chrome(options = options)
        driver.get(url)

        tries = 0
        while True:
            if tries < 20:
                try:
                    # We try until it doesn't fail (so we have the text)
                    # TODO: This 'jscontroller' changes from time to time, pay atention
                    translation = driver.find_elements('xpath', '//*[@jscontroller="JLEx7e"]')[0].get_attribute('innerText')
                    tries = 20
                except Exception as e:
                    # TODO: Uncomment this to see if code error or scrapper error
                    #print(e)
                    tries += 1
                    time.sleep(0.250)
            else:
                break
    finally:
        driver.close()

    return translation