"""
Creates a new r_seleniumbase test file with boilerplate code.

Usage:
    r_seleniumbase mkfile [FILE.py] [OPTIONS]
    or     sbase mkfile [FILE.py] [OPTIONS]

Example:
    sbase mkfile new_test.py

Options:
    --uc  (UC Mode boilerplate using SB context manager)
    -b / --basic  (Basic boilerplate / single-line test)
    -r / --rec  (Adds Pdb+ breakpoint for Recorder Mode)
    --url=URL  (Makes the test start on a specific page)

Language Options:
    --en / --English    |    --zh / --Chinese
    --nl / --Dutch      |    --fr / --French
    --it / --Italian    |    --ja / --Japanese
    --ko / --Korean     |    --pt / --Portuguese
    --ru / --Russian    |    --es / --Spanish

Syntax Formats:
    --bc / --basecase       (BaseCase class inheritance)
    --pf / --pytest-fixture          (sb pytest fixture)
    --cf / --class-fixture   (class + sb pytest fixture)
    --cm / --context-manager        (SB context manager)
    --dc / --driver-context      (DriverContext manager)
    --dm / --driver-manager             (Driver manager)

Output:
    Creates a new SBase test file with boilerplate code.
    If the file already exists, an error is raised.
    By default, uses English with BaseCase inheritance,
    and creates a boilerplate with common r_seleniumbase
    methods: "open", "type", "click", "assert_element",
    and "assert_text". If using the basic boilerplate
    option, only the "open" method is included. Only the
    BaseCase format supports Languages or Recorder Mode.
    UC Mode automatically uses English with SB() format.
"""
import codecs
import colorama
import os
import sys


def invalid_run_command(msg=None):
    exp = "  ** mkfile **\n\n"
    exp += "  Usage:\n"
    exp += "     r_seleniumbase mkfile [FILE.py] [OPTIONS]\n"
    exp += "     OR     sbase mkfile [FILE.py] [OPTIONS]\n"
    exp += "  Example:\n"
    exp += "     sbase mkfile new_test.py\n"
    exp += "  Options:\n"
    exp += "     --uc  (UC Mode boilerplate using SB context manager)\n"
    exp += "     -b / --basic  (Basic boilerplate / single-line test)\n"
    exp += "     -r / --rec  (Adds Pdb+ breakpoint for Recorder Mode)\n"
    exp += "     --url=URL  (Makes the test start on a specific page)\n"
    exp += "  Language Options:\n"
    exp += "     --en / --English    |    --zh / --Chinese\n"
    exp += "     --nl / --Dutch      |    --fr / --French\n"
    exp += "     --it / --Italian    |    --ja / --Japanese\n"
    exp += "     --ko / --Korean     |    --pt / --Portuguese\n"
    exp += "     --ru / --Russian    |    --es / --Spanish\n"
    exp += "  Syntax Formats:\n"
    exp += "     --bc / --basecase       (BaseCase class inheritance)\n"
    exp += "     --pf / --pytest-fixture          (sb pytest fixture)\n"
    exp += "     --cf / --class-fixture   (class + sb pytest fixture)\n"
    exp += "     --cm / --context-manager        (SB context manager)\n"
    exp += "     --dc / --driver-context      (DriverContext manager)\n"
    exp += "     --dm / --driver-manager             (Driver manager)\n"
    exp += "  Output:\n"
    exp += "     Creates a new SBase test file with boilerplate code.\n"
    exp += "     If the file already exists, an error is raised.\n"
    exp += "     By default, uses English with BaseCase inheritance,\n"
    exp += "     and creates a boilerplate with common r_seleniumbase\n"
    exp += '     methods: "open", "type", "click", "assert_element",\n'
    exp += '     and "assert_text". If using the basic boilerplate\n'
    exp += '     option, only the "open" method is included. Only the\n'
    exp += "     BaseCase format supports Languages or Recorder Mode.\n"
    exp += "     UC Mode automatically uses English with SB() format.\n"
    if not msg:
        raise Exception("INVALID RUN COMMAND!\n\n%s" % exp)
    elif msg == "help":
        print("\n%s" % exp)
        sys.exit()
    else:
        raise Exception("INVALID RUN COMMAND!\n\n%s\n%s\n" % (exp, msg))


def main():
    c1 = ""
    c5 = ""
    c7 = ""
    cr = ""
    if "linux" not in sys.platform:
        c1 = colorama.Fore.BLUE + colorama.Back.LIGHTCYAN_EX
        c5 = colorama.Fore.RED + colorama.Back.LIGHTYELLOW_EX
        c7 = colorama.Fore.BLACK + colorama.Back.MAGENTA
        cr = colorama.Style.RESET_ALL

    basic = False
    use_uc = False
    help_me = False
    recorder = False
    error_msg = None
    start_page = None
    invalid_cmd = None
    syntax = "BaseCase"
    language = "English"

    command_args = sys.argv[2:]
    file_name = command_args[0]
    if file_name == "-h" or file_name == "--help":
        invalid_run_command("help")
    elif not file_name.endswith(".py"):
        error_msg = 'File name must end with ".py"!'
    elif "*" in file_name or len(str(file_name)) < 4:
        error_msg = "Invalid file name!"
    elif file_name.startswith("-"):
        error_msg = 'File name cannot start with "-"!'
    elif "/" in str(file_name) or "\\" in str(file_name):
        error_msg = "File must be created in the current directory!"
    elif os.path.exists(os.getcwd() + "/" + file_name):
        error_msg = 'File "%s" already exists in this directory!' % file_name
    if error_msg:
        error_msg = c5 + "ERROR: " + error_msg + cr
        invalid_run_command(error_msg)

    if len(command_args) >= 2:
        options = command_args[1:]
        for option in options:
            option = option.lower()
            if option == "-h" or option == "--help":
                help_me = True
            elif option.startswith("--url=") and len(option) > 6:
                from r_seleniumbase.fixtures import page_utils
                start_page = option.split("--url=")[1]
                if not page_utils.is_valid_url(start_page):
                    if page_utils.is_valid_url("https://" + start_page):
                        start_page = "https://" + start_page
                    else:
                        raise Exception("Invalid URL: %s" % start_page)
                basic = True
            elif option == "-b" or option == "--basic":
                basic = True
            elif option == "-r" or option == "--rec":
                recorder = True
            elif option == "--record" or option == "--recorder":
                recorder = True
            elif use_uc:
                # UC must use English & ContextManager formats
                continue
            elif option == "--en" or option == "--english":
                language = "English"
            elif option == "--zh" or option == "--chinese":
                language = "Chinese"
            elif option == "--nl" or option == "--dutch":
                language = "Dutch"
            elif option == "--fr" or option == "--french":
                language = "French"
            elif option == "--it" or option == "--italian":
                language = "Italian"
            elif option == "--ja" or option == "--japanese":
                language = "Japanese"
            elif option == "--ko" or option == "--korean":
                language = "Korean"
            elif option == "--pt" or option == "--portuguese":
                language = "Portuguese"
            elif option == "--ru" or option == "--russian":
                language = "Russian"
            elif option == "--es" or option == "--spanish":
                language = "Spanish"
            elif option == "--bc" or option == "--basecase":
                syntax = "BaseCase"
            elif option == "--pf" or option == "--pytest-fixture":
                syntax = "PytestFixture"
            elif option == "--cf" or option == "--class-fixture":
                syntax = "ClassFixture"
            elif option == "--cm" or option == "--context-manager":
                syntax = "ContextManager"
            elif option == "--dc" or option == "--driver-context":
                syntax = "DriverContext"
            elif option == "--dm" or option == "--driver-manager":
                syntax = "DriverManager"
            elif option == "--uc":
                basic = True
                language = "English"
                syntax = "ContextManager"
                use_uc = True
            else:
                invalid_cmd = "\n===> INVALID OPTION: >> %s <<\n" % option
                invalid_cmd = invalid_cmd.replace(">> ", ">>" + c5 + " ")
                invalid_cmd = invalid_cmd.replace(" <<", " " + cr + "<<")
                invalid_cmd = invalid_cmd.replace(">>", c7 + ">>" + cr)
                invalid_cmd = invalid_cmd.replace("<<", c7 + "<<" + cr)
                help_me = True
                break
    if help_me:
        invalid_run_command(invalid_cmd)

    dir_name = os.getcwd()
    file_path = "%s/%s" % (dir_name, file_name)

    body = "body"
    para1 = "html body > p"
    para2 = "p"
    hello = "Hello"
    goodbye = "Goodbye"
    class_name = "MyTestClass"
    if language == "Chinese":
        hello = "你好"
        goodbye = "再见"
        class_name = "我的测试类"
    elif language == "Dutch":
        hello = "Hallo"
        goodbye = "Dag"
        class_name = "MijnTestklasse"
    elif language == "French":
        hello = "Bonjour"
        goodbye = "Au revoir"
        class_name = "MaClasseDeTest"
    elif language == "Italian":
        hello = "Ciao"
        goodbye = "Addio"
        class_name = "MiaClasseDiTest"
    elif language == "Japanese":
        hello = "こんにちは"
        goodbye = "さようなら"
        class_name = "私のテストクラス"
    elif language == "Korean":
        hello = "여보세요"
        goodbye = "안녕"
        class_name = "테스트_클래스"
    elif language == "Portuguese":
        hello = "Olá"
        goodbye = "Tchau"
        class_name = "MinhaClasseDeTeste"
    elif language == "Russian":
        hello = "Привет"
        goodbye = "До свидания"
        class_name = "МойТестовыйКласс"
    elif language == "Spanish":
        hello = "Hola"
        goodbye = "Adiós"
        class_name = "MiClaseDePrueba"
    url = ""
    if start_page:
        url = start_page
    elif basic:
        url = "about:blank"
    elif language not in ["English", "Dutch", "French", "Italian"]:
        url = "data:text/html,<meta charset='utf-8'><p>%s<br><input>" % hello
    else:
        url = "data:text/html,<p>%s<br><input>" % hello

    import_line = "from r_seleniumbase import BaseCase"
    main_line = "BaseCase.main(__name__, __file__)"
    parent_class = "BaseCase"
    if language != "English":
        from r_seleniumbase.translate.master_dict import MD_F

        import_line = MD_F.get_import_line(language)
        parent_class = MD_F.get_lang_parent_class(language)
    class_line = "class %s(%s):" % (class_name, parent_class)

    data = []
    data.append("%s" % import_line)
    if not recorder:
        data.append(main_line)
    data.append("")
    data.append("")
    data.append("%s" % class_line)
    data.append("    def test_base(self):")
    if not recorder:
        data.append('        self.open("%s")' % url)
    else:
        data.append("        if self.recorder_ext and not self.xvfb:")
        data.append("            import pdb; pdb.set_trace()")
    if not basic and not recorder:
        data.append(
            '        self.type("input", "%s")' "  # selector, text" % goodbye
        )
        data.append('        self.click("%s")  # selector' % para1)
        data.append('        self.assert_element("%s")  # selector' % body)
        data.append(
            '        self.assert_text("%s", "%s")'
            "  # text, selector" % (hello, para2)
        )
    data.append("")

    new_data = []
    if language == "English" and syntax == "BaseCase":
        new_data = data
    elif language == "English" and syntax == "PytestFixture":
        data = []
        data.append("def test_base(sb):")
        data.append('    sb.open("data:text/html,<p>Hello<br><input>")')
        if not basic:
            data.append('    sb.type("input", "Goodbye")  # selector, text')
            data.append('    sb.click("html body > p")  # selector')
            data.append('    sb.assert_element("body")  # selector')
            data.append('    sb.assert_text("Hello", "p")  # text, selector')
        data.append("")
        new_data = data
    elif language == "English" and syntax == "ClassFixture":
        data = []
        data.append("class %s:" % class_name)
        data.append("    def test_base(self, sb):")
        data.append('        sb.open("data:text/html,<p>Hello<br><input>")')
        if not basic:
            data.append(
                '        sb.type("input", "Goodbye")  # selector, text'
            )
            data.append('        sb.click("html body > p")  # selector')
            data.append('        sb.assert_element("body")  # selector')
            data.append(
                '        sb.assert_text("Hello", "p")  # text, selector'
            )
        data.append("")
        new_data = data
    elif language == "English" and syntax == "ContextManager":
        data = []
        data.append("from r_seleniumbase import SB")
        data.append("")
        if use_uc:
            data.append('with SB(uc=True) as sb:')
        else:
            data.append('with SB(browser="chrome") as sb:')
        if use_uc:
            data.append('    url = "%s"' % url)
            data.append("    sb.uc_open_with_reconnect(url, 4)")
            data.append("    sb.uc_gui_click_captcha()")
        else:
            data.append('    sb.open("%s")' % url)
        if not basic:
            data.append('    sb.type("input", "Goodbye")  # selector, text')
            data.append('    sb.click("html body > p")  # selector')
            data.append('    sb.assert_element("input")  # selector')
            data.append('    sb.assert_text("Hello", "p")  # text, selector')
            data.append('    sb.highlight("p")  # selector')
            data.append("    sb.sleep(0.5)  # seconds")
        data.append("")
        new_data = data
    elif language == "English" and syntax == "DriverContext":
        data = []
        data.append("from r_seleniumbase import DriverContext")
        data.append("")
        data.append('with DriverContext(browser="chrome") as driver:')
        data.append('    driver.get("%s")' % url)
        if not basic:
            data.append('    driver.type("input", "Goodbye")  # sel, text')
            data.append('    driver.click("html body > p")  # selector')
            data.append('    driver.assert_element("input")  # selector')
            data.append('    driver.assert_text("Hello", "p")  # text, sel')
            data.append('    driver.highlight("p")  # selector')
            data.append("    driver.sleep(0.5)  # seconds")
        data.append("")
        new_data = data
    elif language == "English" and syntax == "DriverManager":
        data = []
        data.append("from r_seleniumbase import Driver")
        data.append("")
        data.append('driver = Driver(browser="chrome")')
        data.append("try:")
        data.append('    driver.get("%s")' % url)
        if not basic:
            data.append('    driver.type("input", "Goodbye")  # sel, text')
            data.append('    driver.click("html body > p")  # selector')
            data.append('    driver.assert_element("input")  # selector')
            data.append('    driver.assert_text("Hello", "p")  # text, sel')
            data.append('    driver.highlight("p")  # selector')
            data.append("    driver.sleep(0.5)  # seconds")
        data.append("finally:")
        data.append("    driver.quit()")
        data.append("")
        new_data = data
    else:
        from r_seleniumbase.translate.master_dict import MD
        from r_seleniumbase.translate.master_dict import MD_L_Codes

        md = MD.md
        lang_codes = MD_L_Codes.lang
        nl_code = lang_codes[language]
        dl_code = lang_codes["English"]
        for line in data:
            found_swap = False
            replace_count = line.count("self.")  # Total possible replacements
            for key in md.keys():
                original = "self." + md[key][dl_code] + "("
                if original in line:
                    replacement = "self." + md[key][nl_code] + "("
                    new_line = line.replace(original, replacement)
                    found_swap = True
                    replace_count -= 1
                    if replace_count == 0:
                        break  # Done making replacements
                    else:
                        # There might be another method to replace in the line.
                        # Example: self.assert_true("Name" in self.get_title())
                        line = new_line
                        continue
            if main_line in line:
                new_main = "%s.main(__name__, __file__)" % parent_class
                new_line = line.replace(main_line, new_main)
                found_swap = True
            if found_swap:
                if new_line.endswith("  # noqa"):  # Remove flake8 skip
                    new_line = new_line[0 : -len("  # noqa")]
                new_data.append(new_line)
                continue
            new_data.append(line)
    data = new_data
    file = codecs.open(file_path, "w+", "utf-8")
    file.writelines("\r\n".join(data))
    file.close()
    if " " not in file_name:
        os.system("sbase print %s -n" % file_name)
    elif '"' not in file_name:
        os.system('sbase print "%s" -n' % file_name)
    else:
        os.system("sbase print '%s' -n" % file_name)
    success = (
        "\n" + c1 + '* Test file: "' + file_name + '" was created! *'
        "" + cr + "\n"
    )
    print(success)


if __name__ == "__main__":
    invalid_run_command()
