import os
import tkinter as tk
from tkinter import filedialog as fd
from tkinter.messagebox import showinfo, askyesno, askokcancel
from tkinter import ttk
from pathlib import Path
from deploy import download_ffmpeg, download_git, deploy, get_ffmpeg_version, update
import logging
import sys


def get_curr_screen_geometry():
    """
    Workaround to get the size of the current screen in a multi-screen setup.

    Returns:
        geometry (str): The standard Tk geometry string.
            [width]x[height]+[left]+[top]
    """
    root = tk.Tk()
    root.update_idletasks()
    root.attributes('-fullscreen', True)
    root.state('iconic')
    geometry = root.winfo_geometry()
    root.destroy()

    return geometry


def create_install_frame(container):
    def find_barotrauma_directory():
        first_guess = Path("C:/Program Files (x86)/Steam/steamapps/common/Barotrauma")
        second_guess = Path("D:/Steam/steamapps/common/Barotrauma")

        if first_guess.is_dir():
            return first_guess.as_posix()
        elif second_guess.is_dir():
            return second_guess.as_posix()
        else:
            return False

    def select_barotrauma_directory():
        return_dir = fd.askdirectory(initialdir="C:/")
        install_dir.set(return_dir)

    frame = ttk.LabelFrame(container, text='Barotrauma installation directory')

    find_button = ttk.Button(frame, text='Guess',
                             command=lambda: install_dir.set(find_barotrauma_directory()))
    find_button.pack(side="left", padx=3, pady=3)

    install_dir = tk.StringVar()
    install_dir.set(find_barotrauma_directory())

    directory_entry = ttk.Entry(frame, width=60, textvariable=install_dir)
    directory_entry.pack(side="left", padx=3, pady=3, expand=True, fill="x")

    browse_button = ttk.Button(frame, text='Browse', command=select_barotrauma_directory)
    browse_button.pack(side="left", padx=3, pady=3)

    return frame, install_dir


def create_options_frame(container):
    frame = ttk.LabelFrame(container, text='Options')

    # Use ITA checkbox
    use_ita = tk.StringVar()
    use_ita.set("1")
    use_ita_check = ttk.Checkbutton(
        frame,
        variable=use_ita,
        text='Use ITA mod',
        command=lambda: print(use_ita.get()))

    # Buffs checkbox
    buffs = tk.StringVar()
    buffs.set("1")
    buffs_check = ttk.Checkbutton(
        frame,
        variable=buffs,
        text='Buffs',
        command=lambda: print(buffs.get()))

    # Override Workshop checkbox
    override_workshop = tk.StringVar()
    override_workshop.set("0")
    override_workshop_check = ttk.Checkbutton(
        frame,
        variable=override_workshop,
        text='Override Workshop',
        command=lambda: print(override_workshop.get()))

    for widget in frame.winfo_children():
        widget.pack(side="top", padx=3, pady=3, fill="x")

    return frame, use_ita, buffs, override_workshop


def create_resolution_frame(container):
    frame = ttk.LabelFrame(container, text='Resolution')

    def detect_screen_resolution():
        w, h = get_curr_screen_geometry().split("+")[0].split("x")
        width.set(w)
        height.set(h)

    width = tk.StringVar()
    width.set("1920")
    width_label = ttk.Label(frame, text='Width:')
    width_frame = ttk.Entry(frame, width=12, textvariable=width)

    height = tk.StringVar()
    height.set("1080")
    height_label = ttk.Label(frame, text='Height:')
    height_frame = ttk.Entry(frame, width=12, textvariable=height)

    detect_button = ttk.Button(frame, text='Detect', command=detect_screen_resolution)

    for widget in frame.winfo_children():
        widget.pack(side="left", padx=3, pady=3)

    return frame, width, height


def create_deploy_frame(container, config):
    def deploy_action():
        config_values = {"installdir": config["installdir"].get(),
                         "use_ita": config["use_ita"].get() == "1",
                         "buffs": config["buffs"].get() == "1",
                         "resolution_x": int(config["resolution_x"].get()),
                         "resolution_y": int(config["resolution_x"].get())}

        logging.info(f"deploying with config: {config_values}")
        deploy(config_values)

        showinfo(title='Success!',
                 message=f'Sunken Tapes was successfully installed to:'
                         f'\n{config["installdir"].get()}'
                         f'\n\nThis installer will now close.')

        container.destroy()

    def download_ffmpeg_action():
        def finish():
            does_ffmpeg_exists()
            showinfo(title='Success!',
                     message=f'ffmpeg downloaded. You can now deploy Sunken Tapes:')

        if not Path("./utils/ffmpeg-" + get_ffmpeg_version() + "-full_build/bin/ffmpeg.exe").exists():
            download_ffmpeg()
            finish()
            return
        else:
            answer = askyesno(title='ffmpeg already downloaded',
                              message='ffmpeg is already in utils directory!'
                                      '\n\nDelete the existing one and download again?')

        if answer:
            download_ffmpeg(clean=True)
            finish()
        else:
            return

    def update_action():
        if not Path("./utils/git").exists():
            answer = askokcancel(
                title='Confirmation',
                message='Portable version of git will be downloaded.'
                        '\nThis is needed to check for updates in the repository')
            if answer:
                download_git()
            else:
                return
        else:
            logging.info(f"git already in utils")

        update()

    def does_ffmpeg_exists():
        if Path("./utils/ffmpeg-" + get_ffmpeg_version() + "-full_build/bin/ffmpeg.exe").exists():
            deploy_button["state"] = "normal"
        else:
            deploy_button["state"] = "disable"

    frame = ttk.LabelFrame(container, text='Install')

    frame_1 = ttk.Frame(frame)

    download_tools_label = ttk.Label(frame_1, text='Download and unpack ffmpeg:')
    download_tools_label.pack(side="left", padx=3, pady=3)
    download_tools_button = ttk.Button(frame_1, text='Download', command=download_ffmpeg_action)
    download_tools_button.pack(side="right", padx=3, pady=3)

    frame_1.pack(side="top", fill="x")

    frame_2 = ttk.Frame(frame)

    update_label = ttk.Label(frame_2, text='Download update from git.kompot.si/jaka/barotrauma-sunken-tapes:')
    update_label.pack(side="left", padx=3, pady=3)
    update_button = ttk.Button(frame_2, text='Update', command=update_action)
    update_button.pack(side="right", padx=3, pady=3)

    frame_2.pack(side="top", fill="x")

    frame_3 = ttk.Frame(frame)

    deploy_label = ttk.Label(frame_3, text='Download songs and deploy mod to Barotrauma Mods directory:')
    deploy_label.pack(side="left", padx=3, pady=3)
    deploy_button = ttk.Button(frame_3, text='Deploy', command=deploy_action)
    deploy_button.pack(side="right", padx=3, pady=3)

    frame_3.pack(side="top", fill="x")

    does_ffmpeg_exists()

    return frame


def create_main_window():
    # root window
    root = tk.Tk()
    root.title('Sunken Tapes')
    middle_frame = ttk.Frame(root)

    install_frame, install_dir = create_install_frame(root)
    options_frame, use_ita, buffs, override_workshop = create_options_frame(middle_frame)
    resolution_frame, width, height = create_resolution_frame(middle_frame)

    config = {"installdir": install_dir,
              "use_ita": use_ita,
              "buffs": buffs,
              "override_workshop": override_workshop,
              "resolution_x": width,
              "resolution_y": height_workshop}

    deploy_frame = create_deploy_frame(root, config)

    install_frame.pack(side="top", fill="x", pady=3, padx=3)
    options_frame.pack(side="left", fill="y", pady=3, padx=3)
    resolution_frame.pack(side="left", fill="both", pady=3, padx=3, expand=True)
    middle_frame.pack(side="top", fill="x")
    deploy_frame.pack(side="top", fill="x", pady=3, padx=3)

    root.mainloop()


if __name__ == "__main__":
    os.chdir(Path(__file__).parents[0])
    logging.basicConfig(stream=sys.stdout, level=logging.INFO)
    create_main_window()
