"""
Converts a SeleniumBase Python file into one that uses the Page Object Pattern.

Usage:
        seleniumbase objectify [SELENIUMBASE_PYTHON_FILE].py
Output:
        A modified version of the file where the selectors
        have been replaced with variable names defined in
        "page_objects.py", supporting the Page Object Pattern.
"""

import codecs
import os
import re
import sys
PAGE_OBJECTS_FILE = "page_objects.py"  # Don't change this. It's hard-coded.


def invalid_run_command(shell_command):
    if shell_command == "objectify":
        invalid_objectify_run_command()
    elif shell_command == "inject-objects":
        invalid_inject_objects_run_command()
    elif shell_command == "extract-objects":
        invalid_extract_objects_run_command()
    elif shell_command == "revert-objects":
        invalid_revert_objects_run_command()
    else:
        invalid_objectify_run_command()


def invalid_objectify_run_command():
    exp = ("  ** objectify**\n\n")
    exp += "  Usage:\n"
    exp += "         seleniumbase objectify [SELENIUMBASE_PYTHON_FILE]\n"
    exp += "  Options:\n"
    exp += "         -c, --comments  (Add object selectors to the comments.)\n"
    exp += "                         (Default: No added comments.)\n"
    exp += "  Output:\n"
    exp += "         Converts a SeleniumBase Python file into one that uses\n"
    exp += "         the Page Object Pattern by converting page selectors\n"
    exp += '         into objects stored in a "page_objects.py" file that is\n'
    exp += "         autogenerated and stored in the same folder as tests.\n"
    exp += '         (seleniumbase "objectify" has the same outcome as\n'
    exp += '         combining "extract-objects" with "inject-objects")\n'
    raise Exception('INVALID RUN COMMAND!\n\n%s' % exp)


def invalid_inject_objects_run_command():
    exp = ("  ** inject-objects**\n\n")
    exp += "  Usage:\n"
    exp += "         seleniumbase inject-objects [SELENIUMBASE_PYTHON_FILE]\n"
    exp += "  Options:\n"
    exp += "         -c, --comments  (Add object selectors to the comments.)\n"
    exp += "                         (Default: No added comments.)\n"
    exp += "  Output:\n"
    exp += '         Takes the page objects found in the "page_objects.py"\n'
    exp += "         file and uses those to replace matching selectors in\n"
    exp += "         the selected seleniumbase Python file.\n"
    raise Exception('INVALID RUN COMMAND!\n\n%s' % exp)


def invalid_extract_objects_run_command():
    exp = ("  ** extract-objects**\n\n")
    exp += "  Usage:\n"
    exp += "         seleniumbase extract-objects [SELENIUMBASE_PYTHON_FILE]\n"
    exp += "  Output:\n"
    exp += "         Creates page objects based on selectors found in a\n"
    exp += "         seleniumbase Python file and saves those objects to the\n"
    exp += '         "page_objects.py" file in the same folder as the tests.\n'
    raise Exception('INVALID RUN COMMAND!\n\n%s' % exp)


def invalid_revert_objects_run_command():
    exp = ("  ** revert-objects**\n\n")
    exp += "  Usage:\n"
    exp += "         seleniumbase revert-objects [SELENIUMBASE_PYTHON_FILE]\n"
    exp += "  Options:\n"
    exp += "         -c, --comments  (Keep existing comments for the lines.)\n"
    exp += "                         (Default: No comments are kept.)\n"
    exp += "  Output:\n"
    exp += '         Reverts the changes made by "seleniumbase objectify" or\n'
    exp += '         "seleniumbase inject-objects" when run against a\n'
    exp += '         seleniumbase Python file. Objects will get replaced by\n'
    exp += '         selectors stored in the "page_objects.py" file.\n'
    raise Exception('INVALID RUN COMMAND!\n\n%s' % exp)


def remove_extra_slashes(selector):
    if selector.count('\\"') > 0:
        if selector.count('\\"') == selector.count('"'):
            selector = selector.replace('\\"', '"')
        elif (selector.count('\\"') == selector[1:-1].count('"') and (
              "'" not in selector[1:-1])):
            selector = "'" + selector[1:-1].replace('\\"', '"') + "'"
        else:
            pass
    if selector.count("\\'") > 0:
        if selector.count("\\'") == selector.count("'"):
            selector = selector.replace("\\'", "'")
        elif (selector.count("\\'") == selector[1:-1].count("'") and (
              '"' not in selector[1:-1])):
            selector = '"' + selector[1:-1].replace("\\'", "'") + '"'
        else:
            pass
    return selector


def create_objects_file(selector_list_dict=None):
    data = []
    if selector_list_dict:
        data.append("# -*- coding: utf-8 -*-")
        data.append("# PAGE OBJECTS FILE >>> (autogenerated)")
        data.append("")
        for key in selector_list_dict.keys():
            if key == "None":
                if len(selector_list_dict["None"]) > 0:
                    for pair in selector_list_dict["None"]:
                        data.append("%s = %s" % (pair[0], pair[1]))
                    data.append("")
                else:
                    pass
            else:
                data.append("")
                data.append("class %s(object):" % key)
                for pair in selector_list_dict[key]:
                    data.append("    %s = %s" % (pair[0], pair[1]))
                data.append("")
    else:
        data.append("")
        data.append("class Page(object):")
        data.append('    html = "html"')
        data.append("")
    file_path = PAGE_OBJECTS_FILE
    file = codecs.open(file_path, "w+", "utf-8")
    file.writelines("\r\n".join(data))
    file.close()
    if not selector_list_dict:
        print('\n>>> ["%s"] was created!' % file_path)
    else:
        print('\n>>> ["%s"] was updated!' % file_path)


def scan_objects_file():
    if not os.path.exists(PAGE_OBJECTS_FILE):
        create_objects_file()

    page_selectors = {}
    with open(PAGE_OBJECTS_FILE, 'r', encoding='utf-8') as f:
        all_code = f.read()

    var_names = []
    selectors = []
    current_class = "None"
    selector_list_dict = {}  # Key = class name / Values are name-value tuples
    selector_list_dict[current_class] = []
    selector_list_dict["Page"] = []
    code_lines = all_code.split('\n')
    for line in code_lines:
        line = line.rstrip()
        # Handle: class CLASSNAME(object):  OR  class CLASSNAME():
        data = re.match(
            r'''^(\s*)class\s+([\S]+)\((object|)\):\s*$''', line)
        if data:
            whitespace = data.group(1)
            name = '%s' % data.group(2)
            current_class = name
            selector_list_dict[current_class] = []
            page_selectors["class %s" % name] = "."

        # Handle: SELECTOR_NAME = "SELECTOR"
        data = re.match(
            r'''^(\s*)(\S+)\s*=\s*([\S\s]+)\s*$''', line)
        if data:
            whitespace = data.group(1)
            name = data.group(2)
            selector = data.group(3)
            selector = remove_extra_slashes(selector)
            page_selectors[name] = selector
            var_names.append(name)
            selectors.append(selector)
            if whitespace == "":
                current_class = "None"
            if (len(selector) > 2 and selector[0] == "'") and (
                    selector[-1] == "'" and '"' not in selector[1:-1]):
                selector = '"' + selector[1:-1] + '"'
            if "\\[" in selector or "\\]" in selector or "\\." in selector:
                if selector[0] != "r":
                    selector = "r" + selector
            selector_list_dict[current_class].append((name, selector))

        if "class Page" not in page_selectors.keys():
            page_selectors["class Page"] = '.'

    if len(selector_list_dict["Page"]) == 0:
        selector_list_dict["Page"].append(('html', '"html"'))
    return var_names, selectors, selector_list_dict


def optimize_selector(selector):
    if (len(selector) > 2 and selector[0] == "'") and (
            selector[-1] == "'" and '"' not in selector[1:-1]):
        selector = '"' + selector[1:-1] + '"'
    if "\\[" in selector or "\\]" in selector or "\\." in selector:
        if selector[0] != "r":
            selector = "r" + selector
    return selector


def get_next_var_name(existing_names):
    base_name = "css_"
    for i in range(1, 99999):
        new_name = "%s%s" % (base_name, str(i))
        if new_name not in existing_names:
            return new_name
    raise Exception("Out of range! (Selector name generation)")


def process_test_file(
        code_lines, selector_dict=None, object_dict=None, add_comments=False):

    seleniumbase_lines = []
    page_selectors = []
    changed = []  # The classes of page_objects.py to add to the test import

    for line in code_lines:
        line = line.rstrip()

        # Handle self.click(SELECTOR)
        if not object_dict:
            data = re.match(
                r'''^(\s*)self\.click'''
                r'''\((r?['"][\S\s]+['"])\)([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)self\.click'''
                r'''\(([\S]+)\)([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            selector = '%s' % data.group(2)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            comments = data.group(3)
            command = '''%sself.click(%s)%s''' % (
                whitespace, selector, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%sself.click(%s)%s''' % (
                        whitespace, selector_object, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%sself.click(%s)%s''' % (
                        whitespace, selector_object, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle self.js_click(SELECTOR)
        if not object_dict:
            data = re.match(
                r'''^(\s*)self\.js_click'''
                r'''\((r?['"][\S\s]+['"])\)([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)self\.js_click'''
                r'''\(([\S]+)\)([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            selector = '%s' % data.group(2)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            comments = data.group(3)
            command = '''%sself.js_click(%s)%s''' % (
                whitespace, selector, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%sself.js_click(%s)%s''' % (
                        whitespace, selector_object, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%sself.js_click(%s)%s''' % (
                        whitespace, selector_object, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle self.slow_click(SELECTOR)
        if not object_dict:
            data = re.match(
                r'''^(\s*)self\.slow_click'''
                r'''\((r?['"][\S\s]+['"])\)([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)self\.slow_click'''
                r'''\(([\S]+)\)([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            selector = '%s' % data.group(2)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            comments = data.group(3)
            command = '''%sself.slow_click(%s)%s''' % (
                whitespace, selector, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%sself.slow_click(%s)%s''' % (
                        whitespace, selector_object, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%sself.slow_click(%s)%s''' % (
                        whitespace, selector_object, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle self.click_visible_elements(SELECTOR)
        if not object_dict:
            data = re.match(
                r'''^(\s*)self\.click_visible_elements'''
                r'''\((r?['"][\S\s]+['"])\)([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)self\.click_visible_elements'''
                r'''\(([\S]+)\)([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            selector = '%s' % data.group(2)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            comments = data.group(3)
            command = '''%sself.click_visible_elements(%s)%s''' % (
                whitespace, selector, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%sself.click_visible_elements(%s)%s''' % (
                        whitespace, selector_object, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%sself.click_visible_elements(%s)%s''' % (
                        whitespace, selector_object, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle self.switch_to_frame(SELECTOR)
        if not object_dict:
            data = re.match(
                r'''^(\s*)self\.switch_to_frame'''
                r'''\((r?['"][\S\s]+['"])\)([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)self\.switch_to_frame'''
                r'''\(([\S]+)\)([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            selector = '%s' % data.group(2)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            comments = data.group(3)
            command = '''%sself.switch_to_frame(%s)%s''' % (
                whitespace, selector, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%sself.switch_to_frame(%s)%s''' % (
                        whitespace, selector_object, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%sself.switch_to_frame(%s)%s''' % (
                        whitespace, selector_object, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle self.assert_element(SELECTOR)
        if not object_dict:
            data = re.match(
                r'''^(\s*)self\.assert_element'''
                r'''\((r?['"][\S\s]+['"])\)([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)self\.assert_element'''
                r'''\(([\S]+)\)([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            selector = '%s' % data.group(2)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            comments = data.group(3)
            command = '''%sself.assert_element(%s)%s''' % (
                whitespace, selector, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%sself.assert_element(%s)%s''' % (
                        whitespace, selector_object, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%sself.assert_element(%s)%s''' % (
                        whitespace, selector_object, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle self.assert_element_*(SELECTOR)  *= present/not_visible/absent
        if not object_dict:
            data = re.match(
                r'''^(\s*)self\.assert_element_(\S*)'''
                r'''\((r?['"][\S\s]+['"])\)([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)self\.assert_element_(\S*)'''
                r'''\(([\S]+)\)([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            by_type = data.group(2)
            selector = '%s' % data.group(3)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            comments = data.group(4)
            command = '''%sself.assert_element_%s(%s)%s''' % (
                whitespace, by_type, selector, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%sself.assert_element_%s(%s)%s''' % (
                        whitespace, by_type, selector_object, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%sself.assert_element_%s(%s)%s''' % (
                        whitespace, by_type, selector_object, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle self.find_element(SELECTOR)
        if not object_dict:
            data = re.match(
                r'''^(\s*)self\.find_element'''
                r'''\((r?['"][\S\s]+['"])\)([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)self\.find_element'''
                r'''\(([\S]+)\)([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            selector = '%s' % data.group(2)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            comments = data.group(3)
            command = '''%sself.find_element(%s)%s''' % (
                whitespace, selector, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%sself.find_element(%s)%s''' % (
                        whitespace, selector_object, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%sself.find_element(%s)%s''' % (
                        whitespace, selector_object, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle self.get_element(SELECTOR)
        if not object_dict:
            data = re.match(
                r'''^(\s*)self\.get_element'''
                r'''\((r?['"][\S\s]+['"])\)([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)self\.get_element'''
                r'''\(([\S]+)\)([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            selector = '%s' % data.group(2)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            comments = data.group(3)
            command = '''%sself.get_element(%s)%s''' % (
                whitespace, selector, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%sself.get_element(%s)%s''' % (
                        whitespace, selector_object, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%sself.get_element(%s)%s''' % (
                        whitespace, selector_object, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle self.wait_for_element(SELECTOR)
        if not object_dict:
            data = re.match(
                r'''^(\s*)self\.wait_for_element'''
                r'''\((r?['"][\S\s]+['"])\)([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)self\.wait_for_element'''
                r'''\(([\S]+)\)([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            selector = '%s' % data.group(2)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            comments = data.group(3)
            command = '''%sself.wait_for_element(%s)%s''' % (
                whitespace, selector, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%sself.wait_for_element(%s)%s''' % (
                        whitespace, selector_object, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%sself.wait_for_element(%s)%s''' % (
                        whitespace, selector_object, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle self.wait_for_element_*(SELECTOR)  * = present/visible
        if not object_dict:
            data = re.match(
                r'''^(\s*)self\.wait_for_element_(\S*)'''
                r'''\((r?['"][\S\s]+['"])\)([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)self\.wait_for_element_(\S*)'''
                r'''\(([\S]+)\)([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            by_type = data.group(2)
            selector = '%s' % data.group(3)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            comments = data.group(4)
            command = '''%sself.wait_for_element_%s(%s)%s''' % (
                whitespace, by_type, selector, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%sself.wait_for_element_%s(%s)%s''' % (
                        whitespace, by_type, selector_object, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%sself.wait_for_element_%s(%s)%s''' % (
                        whitespace, by_type, selector_object, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle self.update_text(SELECTOR, TEXT)
        if not object_dict:
            data = re.match(
                r'''^(\s*)self\.update_text'''
                r'''\((r?['"][\S\s]+['"]),\s?([\S\s]+)\)([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)self\.update_text'''
                r'''\(([\S]+),\s?([\S\s]+)\)([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            selector = '%s' % data.group(2)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            text = data.group(3)
            comments = data.group(4)
            command = '''%sself.update_text(%s, %s)%s''' % (
                whitespace, selector, text, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%sself.update_text(%s, %s)%s''' % (
                        whitespace, selector_object, text, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%sself.update_text(%s, %s)%s''' % (
                        whitespace, selector_object, text, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle self.type(SELECTOR, TEXT)
        if not object_dict:
            data = re.match(
                r'''^(\s*)self\.type'''
                r'''\((r?['"][\S\s]+['"]),\s?([\S\s]+)\)([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)self\.type'''
                r'''\(([\S]+),\s?([\S\s]+)\)([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            selector = '%s' % data.group(2)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            text = data.group(3)
            comments = data.group(4)
            command = '''%sself.type(%s, %s)%s''' % (
                whitespace, selector, text, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%sself.type(%s, %s)%s''' % (
                        whitespace, selector_object, text, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%sself.type(%s, %s)%s''' % (
                        whitespace, selector_object, text, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle self.input(SELECTOR, TEXT)
        if not object_dict:
            data = re.match(
                r'''^(\s*)self\.input'''
                r'''\((r?['"][\S\s]+['"]),\s?([\S\s]+)\)([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)self\.input'''
                r'''\(([\S]+),\s?([\S\s]+)\)([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            selector = '%s' % data.group(2)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            text = data.group(3)
            comments = data.group(4)
            command = '''%sself.input(%s, %s)%s''' % (
                whitespace, selector, text, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%sself.input(%s, %s)%s''' % (
                        whitespace, selector_object, text, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%sself.input(%s, %s)%s''' % (
                        whitespace, selector_object, text, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle self.write(SELECTOR, TEXT)
        if not object_dict:
            data = re.match(
                r'''^(\s*)self\.write'''
                r'''\((r?['"][\S\s]+['"]),\s?([\S\s]+)\)([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)self\.write'''
                r'''\(([\S]+),\s?([\S\s]+)\)([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            selector = '%s' % data.group(2)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            text = data.group(3)
            comments = data.group(4)
            command = '''%sself.write(%s, %s)%s''' % (
                whitespace, selector, text, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%sself.write(%s, %s)%s''' % (
                        whitespace, selector_object, text, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%sself.write(%s, %s)%s''' % (
                        whitespace, selector_object, text, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle self.add_text(SELECTOR, TEXT)
        if not object_dict:
            data = re.match(
                r'''^(\s*)self\.add_text'''
                r'''\((r?['"][\S\s]+['"]),\s?([\S\s]+)\)([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)self\.add_text'''
                r'''\(([\S]+),\s?([\S\s]+)\)([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            selector = '%s' % data.group(2)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            text = data.group(3)
            comments = data.group(4)
            command = '''%sself.add_text(%s, %s)%s''' % (
                whitespace, selector, text, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%sself.add_text(%s, %s)%s''' % (
                        whitespace, selector_object, text, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%sself.add_text(%s, %s)%s''' % (
                        whitespace, selector_object, text, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle self.send_keys(SELECTOR, TEXT)
        if not object_dict:
            data = re.match(
                r'''^(\s*)self\.send_keys'''
                r'''\((r?['"][\S\s]+['"]),\s?([\S\s]+)\)([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)self\.send_keys'''
                r'''\(([\S]+),\s?([\S\s]+)\)([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            selector = '%s' % data.group(2)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            text = data.group(3)
            comments = data.group(4)
            command = '''%sself.send_keys(%s, %s)%s''' % (
                whitespace, selector, text, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%sself.send_keys(%s, %s)%s''' % (
                        whitespace, selector_object, text, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%sself.send_keys(%s, %s)%s''' % (
                        whitespace, selector_object, text, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle self.set_value(SELECTOR, TEXT)
        if not object_dict:
            data = re.match(
                r'''^(\s*)self\.set_value'''
                r'''\((r?['"][\S\s]+['"]),\s?([\S\s]+)\)([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)self\.set_value'''
                r'''\(([\S]+),\s?([\S\s]+)\)([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            selector = '%s' % data.group(2)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            text = data.group(3)
            comments = data.group(4)
            command = '''%sself.set_value(%s, %s)%s''' % (
                whitespace, selector, text, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%sself.set_value(%s, %s)%s''' % (
                        whitespace, selector_object, text, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%sself.set_value(%s, %s)%s''' % (
                        whitespace, selector_object, text, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle self.hover_and_click(SELECTOR, SELECTOR)
        if not object_dict:
            data = re.match(
                r'''^(\s*)self\.hover_and_click'''
                r'''\((r?['"][\S\s]+['"]),\s?([\S\s]+)\)([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)self\.hover_and_click'''
                r'''\(([\S]+),\s?([\S]+)\)([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            selector1 = '%s' % data.group(2)
            selector1 = remove_extra_slashes(selector1)
            page_selectors.append(selector1)
            selector2 = '%s' % data.group(3)
            selector2 = remove_extra_slashes(selector2)
            page_selectors.append(selector2)
            comments = data.group(4)
            command = '''%sself.hover_and_click(%s, %s)%s''' % (
                whitespace, selector1, selector2, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector1 = optimize_selector(selector1)
                selector2 = optimize_selector(selector2)
                if selector1 in selector_dict.keys() and (
                        selector2 in selector_dict.keys()):
                    selector_object1 = selector_dict[selector1]
                    selector_object2 = selector_dict[selector2]
                    changed.append(selector_object1.split('.')[0])
                    changed.append(selector_object2.split('.')[0])
                    command = '''%sself.hover_and_click(%s, %s)%s''' % (
                        whitespace, selector_object1, selector_object2,
                        comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name1 = selector1
                object_name2 = selector2
                if object_name1 in object_dict.keys() and (
                        object_name2 in object_dict.keys()):
                    selector_object1 = object_dict[object_name1]
                    selector_object2 = object_dict[object_name2]
                    changed.append(object_name1.split('.')[0])
                    changed.append(object_name2.split('.')[0])
                    command = '''%sself.hover_and_click(%s, %s)%s''' % (
                        whitespace, selector_object1, selector_object2,
                        comments)
            seleniumbase_lines.append(command)
            continue

        # Handle self.press_*_arrow(SELECTOR)
        if not object_dict:
            data = re.match(
                r'''^(\s*)self\.press_(\S*)_arrow'''
                r'''\((r?['"][\S\s]+['"])\)([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)self\.press_(\S*)_arrow'''
                r'''\(([\S]+)\)([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            arrow = '%s' % data.group(2)
            selector = '%s' % data.group(3)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            comments = data.group(4)
            command = '''%sself.press_%s_arrow(%s)%s''' % (
                whitespace, arrow, selector, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%sself.press_%s_arrow(%s)%s''' % (
                        whitespace, arrow, selector_object, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%sself.press_%s_arrow(%s)%s''' % (
                        whitespace, arrow, selector_object, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle self.press_*_arrow(SELECTOR, TIMES)
        if not object_dict:
            data = re.match(
                r'''^(\s*)self\.press_(\S*)_arrow'''
                r'''\((r?['"][\S\s]+['"]),\s?([\S\s]+)\)([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)self\.press_(\S*)_arrow'''
                r'''\(([\S]+),\s?([\S\s]+)\)([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            arrow = '%s' % data.group(2)
            selector = '%s' % data.group(3)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            times = data.group(4)
            comments = data.group(5)
            command = '''%sself.press_%s_arrow(%s, %s)%s''' % (
                whitespace, arrow, selector, times, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%sself.press_%s_arrow(%s, %s)%s''' % (
                        whitespace, arrow, selector_object, times, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%sself.press_%s_arrow(%s, %s)%s''' % (
                        whitespace, arrow, selector_object, times, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle self.assert_text(TEXT, SELECTOR)
        if not object_dict:
            data = re.match(
                r'''^(\s*)self\.assert_text'''
                r'''\(([\S\s]+),\s?(r?['"][\S\s]+['"])\)([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)self\.assert_text'''
                r'''\(([\S\s]+),\s?([\S]+)\)([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            text = data.group(2)
            selector = '%s' % data.group(3)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            comments = data.group(4)
            command = '''%sself.assert_text(%s, %s)%s''' % (
                whitespace, text, selector, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%sself.assert_text(%s, %s)%s''' % (
                        whitespace, text, selector_object, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%sself.assert_text(%s, %s)%s''' % (
                        whitespace, text, selector_object, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle self.assert_exact_text(TEXT, SELECTOR)
        if not object_dict:
            data = re.match(
                r'''^(\s*)self\.assert_exact_text'''
                r'''\(([\S\s]+),\s?(r?['"][\S\s]+['"])\)([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)self\.assert_exact_text'''
                r'''\(([\S\s]+),\s?([\S]+)\)([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            text = data.group(2)
            selector = '%s' % data.group(3)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            comments = data.group(4)
            command = '''%sself.assert_exact_text(%s, %s)%s''' % (
                whitespace, text, selector, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%sself.assert_exact_text(%s, %s)%s''' % (
                        whitespace, text, selector_object, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%sself.assert_exact_text(%s, %s)%s''' % (
                        whitespace, text, selector_object, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle self.find_text(TEXT, SELECTOR)
        if not object_dict:
            data = re.match(
                r'''^(\s*)self\.find_text'''
                r'''\(([\S\s]+),\s?(r?['"][\S\s]+['"])\)([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)self\.find_text'''
                r'''\(([\S\s]+),\s?([\S]+)\)([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            text = data.group(2)
            selector = '%s' % data.group(3)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            comments = data.group(4)
            command = '''%sself.find_text(%s, %s)%s''' % (
                whitespace, text, selector, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%sself.find_text(%s, %s)%s''' % (
                        whitespace, text, selector_object, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%sself.find_text(%s, %s)%s''' % (
                        whitespace, text, selector_object, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle if/elif self.is_text_*(TEXT, SELECTOR):  * = present/visible
        if not object_dict:
            data = re.match(
                r'''^(\s*)(\S*)\sself\.is_text_(\S*)'''
                r'''\(([\S\s]+),\s?(r?['"][\S\s]+['"])\):([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)(\S*)\sself\.is_text_(\S*)'''
                r'''\(([\S\s]+),\s?([\S]+)\):([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            if_type = data.group(2)
            by_type = data.group(3)
            text = data.group(4)
            selector = '%s' % data.group(5)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            comments = data.group(6)
            command = '''%s%s self.is_text_%s(%s, %s):%s''' % (
                whitespace, if_type, by_type, text, selector, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%s%s self.is_text_%s(%s, %s):%s''' % (
                        whitespace, if_type, by_type,
                        text, selector_object, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%s%s self.is_text_%s(%s, %s):%s''' % (
                        whitespace, if_type, by_type,
                        text, selector_object, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle self.wait_for_text(TEXT, SELECTOR)
        if not object_dict:
            data = re.match(
                r'''^(\s*)self\.wait_for_text'''
                r'''\(([\S\s]+),\s?(r?['"][\S\s]+['"])\)([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)self\.wait_for_text'''
                r'''\(([\S\s]+),\s?([\S]+)\)([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            text = data.group(2)
            selector = '%s' % data.group(3)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            comments = data.group(4)
            command = '''%sself.wait_for_text(%s, %s)%s''' % (
                whitespace, text, selector, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%sself.wait_for_text(%s, %s)%s''' % (
                        whitespace, text, selector_object, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%sself.wait_for_text(%s, %s)%s''' % (
                        whitespace, text, selector_object, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle self.wait_for_text_visible(TEXT, SELECTOR)
        if not object_dict:
            data = re.match(
                r'''^(\s*)self\.wait_for_text_visible'''
                r'''\(([\S\s]+),\s?(r?['"][\S\s]+['"])\)([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)self\.wait_for_text_visible'''
                r'''\(([\S\s]+),\s?([\S]+)\)([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            text = data.group(2)
            selector = '%s' % data.group(3)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            comments = data.group(4)
            command = '''%sself.wait_for_text(%s, %s)%s''' % (
                whitespace, text, selector, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%sself.wait_for_text(%s, %s)%s''' % (
                        whitespace, text, selector_object, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%sself.wait_for_text(%s, %s)%s''' % (
                        whitespace, text, selector_object, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle if/elif self.is_element_*(SELECTOR):  * = present/visible
        if not object_dict:
            data = re.match(
                r'''^(\s*)(\S*)\sself\.is_element_(\S*)'''
                r'''\((r?['"][\S\s]+['"])\):([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)(\S*)\sself\.is_element_(\S*)'''
                r'''\(([\S]+)\):([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            if_type = data.group(2)
            by_type = data.group(3)
            selector = '%s' % data.group(4)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            comments = data.group(5)
            command = '''%s%s self.is_element_%s(%s):%s''' % (
                whitespace, if_type, by_type, selector, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%s%s self.is_element_%s(%s):%s''' % (
                        whitespace, if_type, by_type,
                        selector_object, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%s%s self.is_element_%s(%s):%s''' % (
                        whitespace, if_type, by_type,
                        selector_object, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle if/elif self.is_selected(SELECTOR):
        if not object_dict:
            data = re.match(
                r'''^(\s*)(\S*)\sself\.is_selected'''
                r'''\((r?['"][\S\s]+['"])\):([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)(\S*)\sself\.is_selected'''
                r'''\(([\S]+)\):([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            if_type = data.group(2)
            selector = '%s' % data.group(3)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            comments = data.group(4)
            command = '''%s%s self.is_selected(%s):%s''' % (
                whitespace, if_type, selector, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%s%s self.is_selected(%s):%s''' % (
                        whitespace, if_type, selector_object, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%s%s self.is_selected(%s):%s''' % (
                        whitespace, if_type, selector_object, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle self.assert*(self.is_selected(SELECTOR))
        if not object_dict:
            data = re.match(
                r'''^(\s*)self\.assert(\S*)\(self\.is_selected'''
                r'''\((r?['"][\S\s]+['"])\)\)([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)self\.assert(\S*)\(self\.is_selected'''
                r'''\(([\S]+)\)\)([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            a_type = data.group(2)
            selector = '%s' % data.group(3)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            comments = data.group(4)
            command = '''%sself.assert%s(self.is_selected(%s))%s''' % (
                whitespace, a_type, selector, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%sself.assert%s(self.is_selected(%s))%s''' % (
                        whitespace, a_type, selector_object, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%sself.assert%s(self.is_selected(%s))%s''' % (
                        whitespace, a_type, selector_object, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle self.assert*(self.is_element_*(SELECTOR))
        if not object_dict:
            data = re.match(
                r'''^(\s*)self\.assert(\S*)\(self\.is_element_(\S*)'''
                r'''\((r?['"][\S\s]+['"])\)\)([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)self\.assert(\S*)\(self\.is_element_(\S*)'''
                r'''\(([\S]+)\)\)([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            a_type = data.group(2)
            v_type = data.group(3)
            selector = '%s' % data.group(4)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            comments = data.group(5)
            command = '''%sself.assert%s(self.is_element_%s(%s))%s''' % (
                whitespace, a_type, v_type, selector, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '%sself.assert%s(self.is_element_%s(%s))%s' % (
                        whitespace, a_type, v_type, selector_object, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '%sself.assert%s(self.is_element_%s(%s))%s' % (
                        whitespace, a_type, v_type, selector_object, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle VAR = self.get_attribute(SELECTOR, ATTRIBUTE)
        if not object_dict:
            data = re.match(
                r'''^(\s*)(\S*)\s?=\s?self\.get_attribute'''
                r'''\((r?['"][\S\s]+['"]),\s?(['"][\S\s]+['"])\)([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)(\S*)\s?=\s?self\.get_attribute'''
                r'''\(([\S]+),\s?(['"][\S\s]+['"])\)([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            var_name = data.group(2)
            selector = '%s' % data.group(3)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            attribute = data.group(4)
            comments = data.group(5)
            command = '''%s%s = self.get_attribute(%s, %s)%s''' % (
                whitespace, var_name, selector, attribute, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%s%s = self.get_attribute(%s, %s)%s''' % (
                        whitespace, var_name,
                        selector_object, attribute, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%s%s = self.get_attribute(%s, %s)%s''' % (
                        whitespace, var_name,
                        selector_object, attribute, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle VAR = self.get_text(SELECTOR)
        if not object_dict:
            data = re.match(
                r'''^(\s*)(\S*)\s?=\s?self\.get_text'''
                r'''\((r?['"][\S\s]+['"])\)([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)(\S*)\s?=\s?self\.get_text'''
                r'''\(([\S]+)\)([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            var_name = data.group(2)
            selector = '%s' % data.group(3)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            comments = data.group(4)
            command = '''%s%s = self.get_text(%s)%s''' % (
                whitespace, var_name, selector, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%s%s = self.get_text(%s)%s''' % (
                        whitespace, var_name, selector_object, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%s%s = self.get_text(%s)%s''' % (
                        whitespace, var_name, selector_object, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle if VAR [in|not in] self.get_text(SELECTOR):
        if not object_dict:
            data = re.match(
                r'''^(\s*)if\s(\S*\s?\S*)\sin\s?self\.get_text'''
                r'''\((r?['"][\S\s]+['"])\):([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)if\s(\S*\s?\S*)\sin\s?self\.get_text'''
                r'''\(([\S]+)\):([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            var_prefix = data.group(2)
            selector = '%s' % data.group(3)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            comments = data.group(4)
            command = '''%sif %s in self.get_text(%s):%s''' % (
                whitespace, var_prefix, selector, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%sif %s in self.get_text(%s):%s''' % (
                        whitespace, var_prefix, selector_object, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%sif %s in self.get_text(%s):%s''' % (
                        whitespace, var_prefix, selector_object, comments)
            seleniumbase_lines.append(command)
            continue

        # Handle self.select_option_by_*(SELECTOR, TEXT)  * = index/value/text
        if not object_dict:
            data = re.match(
                r'''^(\s*)self\.select_option_by_(\S*)'''
                r'''\((r?['"][\S\s]+['"]),\s?([\S\s]+)\)([\S\s]*)'''
                r'''$''', line)
        else:
            data = re.match(
                r'''^(\s*)self\.select_option_by_(\S*)'''
                r'''\(([\S]+),\s?([\S\s]+)\)([\S\s]*)'''
                r'''$''', line)
        if data:
            whitespace = data.group(1)
            by_type = data.group(2)
            selector = '%s' % data.group(3)
            selector = remove_extra_slashes(selector)
            page_selectors.append(selector)
            text = data.group(4)
            comments = data.group(5)
            command = '''%sself.select_option_by_%s(%s, %s)%s''' % (
                whitespace, by_type, selector, text, comments)
            if selector_dict:
                if add_comments:
                    comments = "  # %s" % selector
                selector = optimize_selector(selector)
                if selector in selector_dict.keys():
                    selector_object = selector_dict[selector]
                    changed.append(selector_object.split('.')[0])
                    command = '''%sself.select_option_by_%s(%s, %s)%s''' % (
                        whitespace, by_type, selector_object, text, comments)
            if object_dict:
                if not add_comments:
                    comments = ""
                object_name = selector
                if object_name in object_dict.keys():
                    selector_object = object_dict[object_name]
                    changed.append(object_name.split('.')[0])
                    command = '''%sself.select_option_by_%s(%s, %s)%s''' % (
                        whitespace, by_type, selector_object, text, comments)
            seleniumbase_lines.append(command)
            continue

        # seleniumbase_lines.append("### " + line)  # untouched lines (Debug)
        seleniumbase_lines.append(line)
        continue

    return seleniumbase_lines, page_selectors, changed


def extract_objects():
    main(shell_command="extract-objects")


def inject_objects():
    main(shell_command="inject-objects")


def objectify():
    main(shell_command="objectify")


def revert_objects():
    main(shell_command="revert-objects")


def main(shell_command):
    expected_arg = ("[A SeleniumBase Python file]")
    num_args = len(sys.argv)
    command_args = sys.argv[2:]

    add_comments = False
    if shell_command == "objectify" or (
            shell_command == "inject-objects" or (
                shell_command == "revert-objects")):
        if len(command_args) >= 2:
            options = command_args[1:]
            for option in options:
                if option == '-c' or option == '--comments':
                    add_comments = True
                else:
                    invalid_run_command(shell_command)

    if sys.argv[0].split('/')[-1] == "seleniumbase" or (
            sys.argv[0].split('\\')[-1] == "seleniumbase") or (
            sys.argv[0].split('/')[-1] == "sbase") or (
            sys.argv[0].split('\\')[-1] == "sbase"):
        if num_args < 3:
            invalid_run_command(shell_command)
        elif num_args > 3:
            if shell_command == "extract-objects":
                invalid_run_command(shell_command)
            else:
                pass
        else:
            pass
    else:
        invalid_run_command(shell_command)

    seleniumbase_file = command_args[0]
    if not seleniumbase_file.endswith('.py'):
        raise Exception("\n\n`%s` is not a Python file!\n\n"
                        "Expecting: %s\n"
                        % (seleniumbase_file, expected_arg))

    with open(seleniumbase_file, 'r', encoding='utf-8') as f:
        all_code = f.read()
    if "def test_" not in all_code:
        raise Exception("\n\n`%s` is not a valid SeleniumBase unittest file!\n"
                        "\nExpecting: %s\n"
                        % (seleniumbase_file, expected_arg))
    code_lines = all_code.split('\n')
    seleniumbase_lines, page_selectors, changed = process_test_file(code_lines)
    var_names, existing_selectors, selector_list_dict = scan_objects_file()
    new_page_selectors = []

    for selector in page_selectors:
        selector = optimize_selector(selector)
        if selector not in existing_selectors:
            new_page_selectors.append(selector)
            var_name = get_next_var_name(var_names)
            var_names.append(var_name)
            selector_list_dict["Page"].append((var_name, selector))
            existing_selectors.append(selector)

    # print(new_page_selectors)  # (For debugging)
    # print(selector_list_dict)  # (For debugging)

    if shell_command == "extract-objects" or shell_command == "objectify":
        create_objects_file(selector_list_dict)

    if shell_command == "extract-objects":
        print("")
        return

    selector_dict = {}  # Key: selector, Value: object
    object_dict = {}  # Key: object, Value: selector
    for key in selector_list_dict.keys():
        for pair in selector_list_dict[key]:
            selector_dict[pair[1]] = "%s.%s" % (str(key), str(pair[0]))
            object_name = "%s.%s" % (str(key), str(pair[0]))
            object_dict[object_name] = pair[1]

    good_sel_dict = {}
    aa, bb, cc = scan_objects_file()
    for s_key in selector_dict.keys():
        if s_key in bb:
            good_sel_dict[s_key] = selector_dict[s_key]

    if shell_command == "inject-objects" or shell_command == "objectify":
        seleniumbase_lines, page_selectors, changed = process_test_file(
            code_lines, selector_dict=good_sel_dict, add_comments=add_comments)
        added_classes = []
        for item in changed:
            if item not in added_classes:
                added_classes.append(item)
        for line in seleniumbase_lines:
            if "from .page_objects import" in line:
                token = line.split("from .page_objects import ")[1].strip()
                if token in added_classes:
                    # Don't import page_objects classes if already imported
                    added_classes.remove(token)
        if added_classes:
            sb_lines = []
            fit_in = False
            for line in seleniumbase_lines:
                if line.startswith("from") and "import" in line and not fit_in:
                    fit_in = True
                    for add_me in added_classes:
                        import_line = "from .page_objects import %s" % add_me
                        sb_lines.append(import_line)
                sb_lines.append(line)
            seleniumbase_lines = sb_lines

    if shell_command == "revert-objects":
        seleniumbase_lines, page_selectors, changed = process_test_file(
            code_lines, object_dict=object_dict, add_comments=add_comments)
        removed_classes = []
        for item in changed:
            if item not in removed_classes:
                removed_classes.append(item)
        if removed_classes:
            sb_lines = []
            for line in seleniumbase_lines:
                if "from .page_objects import" in line:
                    token = line.split("from .page_objects import ")[1].strip()
                    if token in removed_classes:
                        continue
                sb_lines.append(line)
            seleniumbase_lines = sb_lines

    seleniumbase_code = ""
    for line in seleniumbase_lines:
        seleniumbase_code += line
        seleniumbase_code += "\n"
    seleniumbase_code = seleniumbase_code[:-1]
    # print (seleniumbase_code)  # (For debugging)

    # Create SeleniumBase test file
    base_file_name = seleniumbase_file.split('.py')[0]
    converted_file_name = base_file_name + ".py"  # Change end to make a copy
    out_file = codecs.open(converted_file_name, "w+", encoding="utf-8")
    out_file.writelines(seleniumbase_code)
    out_file.close()
    print('\n>>> ["%s"] was updated!\n' % converted_file_name)


if __name__ == "__main__":
    invalid_objectify_run_command()
