"""
** recorder **

Launches the SeleniumBase Recorder Desktop App.

Usage:
    seleniumbase recorder [OPTIONS]
           sbase recorder [OPTIONS]

Options:
    --uc / --undetected  (Use undetectable mode.)
    --cdp  (Same as "--uc" and "--undetectable".)
    --behave  (Also output Behave/Gherkin files.)

Output:
    Launches the SeleniumBase Recorder Desktop App.
"""
import colorama
import os
import subprocess
import sys
import tkinter as tk
from seleniumbase import config as sb_config
from seleniumbase.fixtures import page_utils
from seleniumbase.fixtures import shared_utils
from tkinter import messagebox

sb_config.rec_subprocess_p = None
sb_config.rec_subprocess_used = False
sys_executable = sys.executable
if " " in sys_executable:
    sys_executable = "python"


def set_colors(use_colors):
    c0 = ""
    c1 = ""
    c2 = ""
    c3 = ""
    c4 = ""
    cr = ""
    if use_colors:
        c0 = colorama.Fore.BLUE + colorama.Back.LIGHTCYAN_EX
        c1 = colorama.Fore.BLUE + colorama.Back.LIGHTGREEN_EX
        c2 = colorama.Fore.RED + colorama.Back.LIGHTYELLOW_EX
        c3 = colorama.Fore.LIGHTRED_EX + colorama.Back.LIGHTYELLOW_EX
        c4 = colorama.Fore.BLUE + colorama.Back.LIGHTYELLOW_EX
        cr = colorama.Style.RESET_ALL
    return c0, c1, c2, c3, c4, cr


def send_window_to_front(window):
    window.lift()
    window.attributes("-topmost", True)
    window.after_idle(window.attributes, "-topmost", False)


def show_already_recording_warning():
    messagebox.showwarning(
        "SeleniumBase Recorder: Already Running!",
        "Please finalize the active recording from the terminal\n"
        'where you opened the Recorder: Type "c" and hit Enter.',
    )


def file_name_error(file_name):
    error_msg = None
    if 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!"
    return error_msg


def do_recording(file_name, url, overwrite_enabled, use_chrome, window):
    poll = None
    if sb_config.rec_subprocess_used:
        poll = sb_config.rec_subprocess_p.poll()
    if not sb_config.rec_subprocess_used or poll is not None:
        pass
    else:
        show_already_recording_warning()
        send_window_to_front(window)
        poll = sb_config.rec_subprocess_p.poll()
        if poll is None:
            return

    file_name = file_name.strip()
    error_msg = file_name_error(file_name)
    if error_msg:
        messagebox.showwarning(
            "Invalid filename", "Invalid filename: %s" % error_msg
        )
        return

    url = url.strip()
    if not page_utils.is_valid_url(url):
        if page_utils.is_valid_url("https://" + url):
            url = "https://" + url
    if not page_utils.is_valid_url(url):
        messagebox.showwarning(
            "Invalid URL", "Enter a valid URL! (Eg. seleniumbase.io)"
        )
    else:
        if os.path.exists(os.getcwd() + "/" + file_name):
            if not overwrite_enabled:
                msgbox = tk.messagebox.askquestion(
                    "Overwrite?",
                    'Are you sure you want to overwrite "%s"?' % file_name,
                    icon="warning",
                )
                if msgbox == "yes":
                    os.remove(file_name)
                else:
                    tk.messagebox.showinfo("Cancelled", "Recording Cancelled!")
                    return
            else:
                os.remove(file_name)
        add_on = ""
        command_args = sys.argv[2:]
        if (
            "--rec-behave" in command_args
            or "--behave" in command_args
            or "--gherkin" in command_args
        ):
            add_on = " --rec-behave"
        command = (
            "%s -m seleniumbase mkrec %s --url=%s --gui"
            % (sys_executable, file_name, url)
        )
        if '"' not in url:
            command = (
                '%s -m seleniumbase mkrec %s --url="%s" --gui'
                % (sys_executable, file_name, url)
            )
        elif "'" not in url:
            command = (
                "%s -m seleniumbase mkrec %s --url='%s' --gui"
                % (sys_executable, file_name, url)
            )
        if not use_chrome:
            command += " --edge"
        elif "--opera" in command_args:
            command += " --opera"
        elif "--brave" in command_args:
            command += " --brave"
        elif "--comet" in command_args:
            command += " --comet"
        elif "--atlas" in command_args:
            command += " --atlas"
        elif "--use-chromium" in command_args:
            command += " --use-chromium"
        if (
            "--uc" in command_args
            or "--cdp" in command_args
            or "--undetected" in command_args
            or "--undetectable" in command_args
        ):
            command += " --uc"
        if "--ee" in command_args:
            command += " --ee"
        command += add_on
        poll = None
        if sb_config.rec_subprocess_used:
            poll = sb_config.rec_subprocess_p.poll()
        if not sb_config.rec_subprocess_used or poll is not None:
            sb_config.rec_subprocess_p = subprocess.Popen(command, shell=True)
            sb_config.rec_subprocess_used = True
        else:
            show_already_recording_warning()
        send_window_to_front(window)


def do_playback(file_name, use_chrome, window, demo_mode=False):
    file_name = file_name.strip()
    error_msg = file_name_error(file_name)
    if error_msg:
        messagebox.showwarning(
            "Invalid filename", "Invalid filename: %s" % error_msg
        )
        return
    if not os.path.exists(os.getcwd() + "/" + file_name):
        messagebox.showwarning(
            "File does not exist",
            'File "%s" does not exist in the current directory!' % file_name,
        )
        return
    command = "%s -m pytest %s -q -s" % (sys_executable, file_name)
    if shared_utils.is_linux():
        command += " --gui"
    if not use_chrome:
        command += " --edge"
    if demo_mode:
        command += " --demo"
    command_args = sys.argv[2:]
    if (
        "--uc" in command_args
        or "--cdp" in command_args
        or "--undetected" in command_args
        or "--undetectable" in command_args
    ):
        command += " --uc"
    poll = None
    if sb_config.rec_subprocess_used:
        poll = sb_config.rec_subprocess_p.poll()
    if not sb_config.rec_subprocess_used or poll is not None:
        print(command)
        subprocess.Popen(command, shell=True)
    else:
        messagebox.showwarning(
            "SeleniumBase Recorder: Already Running!",
            "Please finalize the active recording from the terminal\n"
            'where you opened the Recorder: Type "c" and hit Enter.',
        )
    send_window_to_front(window)


def create_tkinter_gui():
    default_file_name = "new_recording.py"
    window = tk.Tk()
    window.title("SeleniumBase Recorder App")
    window.geometry("344x388")
    frame = tk.Frame(window)
    frame.pack()

    tk.Label(window, text="").pack()
    fname = tk.StringVar(value=default_file_name)
    tk.Label(window, text="Enter filename to save recording as:").pack()
    entry = tk.Entry(window, textvariable=fname)
    entry.pack()
    cbx = tk.IntVar()
    chk = tk.Checkbutton(window, text="Overwrite existing files", variable=cbx)
    chk.pack()
    chk.select()
    use_stealth = False
    command_args = sys.argv[2:]
    if (
        "--uc" in command_args
        or "--cdp" in command_args
        or "--undetected" in command_args
        or "--undetectable" in command_args
    ):
        use_stealth = True
    browser_display = "Use Chrome over Edge"
    if "--opera" in command_args:
        browser_display = "Use Opera over Edge"
    elif "--brave" in command_args:
        browser_display = "Use Brave over Edge"
    elif "--comet" in command_args:
        browser_display = "Use Comet over Edge"
    elif "--atlas" in command_args:
        browser_display = "Use Atlas over Edge"
    cbb = tk.IntVar()
    if not use_stealth:
        chkb = tk.Checkbutton(window, text=browser_display, variable=cbb)
        chkb.pack()
        if "--edge" not in command_args:
            chkb.select()
    else:
        chkb = tk.Checkbutton(
            window, text="Stealthy Chrome Mode", variable=cbb
        )
        chkb.pack()
        chkb.select()
        chkb.config(state=tk.DISABLED)
    tk.Label(window, text="").pack()
    url = tk.StringVar()
    tk.Label(window, text="Enter the URL to start recording on:").pack()
    entry = tk.Entry(window, textvariable=url)
    entry.pack()
    entry.focus()
    entry.bind(
        "<Return>",
        (
            lambda _: do_recording(
                fname.get(), url.get(), cbx.get(), cbb.get(), window
            )
        ),
    )
    tk.Button(
        window,
        text="Record",
        fg="red",
        command=lambda: do_recording(
            fname.get(), url.get(), cbx.get(), cbb.get(), window
        ),
    ).pack()
    tk.Label(window, text="").pack()
    tk.Label(window, text="Playback recording (Normal Mode):").pack()
    tk.Button(
        window,
        text="Playback",
        fg="green",
        command=lambda: do_playback(fname.get(), cbb.get(), window),
    ).pack()
    tk.Label(window, text="").pack()
    tk.Label(window, text="Playback recording (Demo Mode):").pack()
    try:
        tk.Button(
            window,
            text="Playback (Demo Mode)",
            fg="teal",
            command=lambda: do_playback(
                fname.get(), cbb.get(), window, demo_mode=True
            ),
        ).pack()
    except Exception:
        tk.Button(
            window,
            text="Playback (Demo Mode)",
            fg="blue",
            command=lambda: do_playback(
                fname.get(), cbb.get(), window, demo_mode=True
            ),
        ).pack()

    # Bring form window to front
    send_window_to_front(window)
    # Use decoy to set correct focus on main window
    decoy = tk.Tk()
    decoy.geometry("1x1")
    decoy.iconify()
    decoy.update()
    decoy.deiconify()
    decoy.destroy()
    # Start tkinter
    window.mainloop()
    end_program()


def recorder_still_running():
    poll = None
    if sb_config.rec_subprocess_used:
        try:
            poll = sb_config.rec_subprocess_p.poll()
        except Exception:
            return False
    else:
        return False
    if poll is not None:
        return False
    return True


def show_still_running_warning():
    """Give the user a chance to end the recording safely via the
    pytest pdb Debug Mode so that processes such as chromedriver
    and Python don't remain open and hanging in the background."""
    messagebox.showwarning(
        "SeleniumBase Recorder: Still Running!",
        "Please finalize the active recording from the terminal\n"
        'where you opened the Recorder: Type "c" and hit Enter.\n'
        "(Then you can safely close this alert.)",
    )


def end_program():
    if recorder_still_running():
        show_still_running_warning()


def main():
    use_colors = True
    if shared_utils.is_linux():
        use_colors = False
    c0, c1, c2, c3, c4, cr = set_colors(use_colors)
    message = ""
    message += c2
    message += "*"
    message += c4
    message += " Starting the "
    message += c0
    message += "Selenium"
    message += c1
    message += "Base"
    message += c2
    message += " "
    message += c3
    message += "Recorder"
    message += c4
    message += " Desktop App"
    message += c2
    message += "..."
    message += cr
    print(message)
    create_tkinter_gui()


if __name__ == "__main__":
    print('To open the Recorder Desktop App: "seleniumbase recorder"')
