#!/usr/bin/python3

import json
import sys
import os
from urllib import request
import shutil
import subprocess

HOME = os.path.expanduser("~")
STEAM_PATH = HOME + "/.steam/steam/steamapps/common/"
IS_FLATPAK = False

class Style:
    HEADER = '\033[95m'
    OKBLUE = '\033[94m'
    OKCYAN = '\033[96m'
    OKGREEN = '\033[92m'
    WARNING = '\033[93m'
    FAIL = '\033[91m'
    END = '\033[0m'
    BOLD = '\033[1m'
    UNDERLINE = '\033[4m'

def ask(question: str) -> bool:
    i = input(question + " [Y/N] ")
    return i.lower() in ["yes", "y"]

def steam_source():
    global STEAM_PATH
    global IS_FLATPAK
    steam_system_path = HOME + "/.local/share/Steam/"
    steam_flatpak_path = HOME + "/.var/app/com.valvesoftware.Steam/.local/share/Steam/"
    steam_flatpak_apps_path = steam_flatpak_path + "steamapps/common/"
    if os.path.isdir(steam_flatpak_path) and os.path.isdir(steam_system_path):
        print(f"{Style.OKBLUE}You have steam client installed on both system and flatpak!{Style.END}")
        print("Which steam client do you want to use for?")
        confirm = ask("Y - choose for system, N - choose for flatpak")
        if not confirm:
            STEAM_PATH = steam_flatpak_apps_path
            IS_FLATPAK = True
            print(f"{Style.OKBLUE}Chosen flatpak!{Style.END}")
        else:
            print(f"{Style.OKBLUE}Chosen system!{Style.END}")
    elif not os.path.isdir(steam_system_path):
        STEAM_PATH = steam_flatpak_apps_path
        IS_FLATPAK = True
    elif not os.path.isdir(steam_system_path) and not os.path.isdir(steam_flatpak_path):
        print(f"{Style.FAIL}You don't have Steam client installed! Please install first.{Style.END}")
        sys.exit(1)


def proton_sources():
    global IS_FLATPAK
    steam_arr = [{"name": l, "path": STEAM_PATH} for l in os.listdir(STEAM_PATH) if "proton" in l.lower()]
    if IS_FLATPAK:
        steam_compartibility_path = HOME + "/.var/app/com.valvesoftware.Steam/.local/share/Steam/compatibilitytools.d/"
    else:
        steam_compartibility_path = HOME + "/.local/share/Steam/compatibilitytools.d/"
    comp_arr = [{"name": l, "path": steam_compartibility_path} for l in os.listdir(steam_compartibility_path) if "proton" in l.lower()]
    return steam_arr + comp_arr


def check_version():
    ver = sys.version_info
    if ver[0] < 3:
        print(f"{Style.FAIL}Python 2 is not supported.{Style.END}")
        sys.exit(1)
    elif ver[1] < 8:
        print(f"{Style.FAIL}Python 3.7 and under are not supported.\nIf your distro only offers older version of python please use pyenv.{Style.END}")
        sys.exit(1)


def create_config_if_not_exist(j=None):
    config_path = HOME + "/.config/proton-cli"
    if not os.path.isdir(config_path):
        os.makedirs(config_path)
    if not os.path.isfile(config_path + "/config.json"):
        with open(config_path + "/config.json", "w") as f:
            JSON = {
                "RPC": {
                    "enable": False,
                    "path": None
                },
                "PROTON_PATH": None,
                "ARGUMENTS": []
            } if not j else j
            json.dump(JSON, f)
            f.close()


def create_local_if_not_exists():
    local_path = HOME + "/.local/share/proton-cli"
    if not os.path.isdir(local_path):
        os.makedirs(local_path)
    if not os.path.isdir(local_path + "/proton"):
        os.makedirs(local_path + "/proton")


def get_config():
    create_config_if_not_exist()
    with open(HOME + "/.config/proton-cli/config.json") as f:
        j = json.load(f)
        f.close()
        return j


def select_proton_version():
    def write(ver):
        name = ver["name"]
        path = ver["path"]
        config = get_config()
        config["PROTON_PATH"] = os.path.join(
            HOME, path, name, "proton")
        with open(HOME + "/.config/proton-cli/config.json", "w") as f:
            json.dump(config, f)
            f.close()

    li = proton_sources()
    if len(li) < 1:
        print(f"{Style.FAIL}Looks like there's no Proton installed. Please install it first.{Style.END}")
        sys.exit(1)
    elif len(li) == 1:
        i = ask(f"{Style.HEADER}Select {li[0]['name']}?{Style.END}")
        if not i:
            print(f"{Style.OKCYAN}Cancelled{Style.END}")
            sys.exit(0)
        else:
            write(li[0])
    else:
        fil = [f"{l['name']} from {l['path']}" for l in li]
        index = 0
        for i in fil:
            print(f"{index} - {fil[index]}")
            index+=1
        print(f"{Style.HEADER}Detected multiple Proton installers. Type the following index to select Proton you want to use{Style.END}")
        while True:
            try:
                num = input("> ")
                realnum = int(num)
                chosen_proton = li[realnum]
                print(f"{Style.OKGREEN}You have selected {chosen_proton['name']}!{Style.END}")
                write(chosen_proton)
                break
            except KeyboardInterrupt:
                sys.exit()
            except:
                continue


def enable_RPC():
    create_local_if_not_exists()
    h = ask(f"{Style.HEADER}Do you want to enable support for Discord Rich Presence?{Style.END}")
    if not h:
        return
    else:
        local_path = HOME + "/.local/share/proton-cli"
        exe = os.path.join(local_path, "winediscordipcbridge.exe")
        print(f"{Style.OKBLUE}Downloading winediscordipcbridge.exe...{Style.END}")
        request.urlretrieve(
            "https://github.com/0e4ef622/wine-discord-ipc-bridge/releases/download/v0.0.2/winediscordipcbridge.exe", exe)
        config = get_config()
        config["RPC"] = {
            "enable": True,
            "path": exe
        }
        with open(HOME + "/.config/proton-cli/config.json", "w") as f:
            json.dump(config, f)
            f.close()
        print("Done!")


def get_latest_commit():
    b = subprocess.check_output(["git", "log", "--pretty=format:'%h'", "-1"])
    s = b.decode().replace("'", '')
    return s


def install():
    dest_bins = os.path.join(HOME, ".local", "bin") + "/"
    print(f"Copying binary files to {dest_bins}...")
    bins = os.path.join(os.getcwd(), "bin")
    if not os.path.isdir(bins):
        print("Failed to install: Cannot find bin directory.")
        sys.exit(2)
    if not os.path.isdir(dest_bins):
        os.mkdir(dest_bins)
    for files in os.listdir(bins):
        shutil.copy2(os.path.join(bins, files), dest_bins)
    print("Done!")


def check_path():
    p = os.environ["PATH"].split(os.pathsep)
    if not f"{HOME}/.local/bin" in p:
        confirm = ask(
            f"{Style.HEADER}Do you want to add {HOME}/.local/bin to the PATH env? This will allow to use commands in Terminal.{Style.END}")
        if not confirm:
            print("Ok. Don't forget to set the PATH manually!")
            return
        else:
            os.environ["PATH"] += os.pathsep + f"{HOME}/.local/bin"
            print(f"Added {HOME}/.local/bin to the PATH env!")


def write_to_version():
    local_path = HOME + "/.local/share/proton-cli"
    version = get_latest_commit()
    with open(os.path.join(local_path, "version"), "w") as f:
        f.write(version)
        f.close()


if __name__ == "__main__":
    try:
        arg = sys.argv[1]
    except IndexError:
        arg = ''
    if len(sys.argv[1:]) < 1:
        steam_source()
        check_version()
        select_proton_version()
        enable_RPC()
        install()
        write_to_version()
        check_path()
        print(f"""Sucessfully installed! You can now use the following commands:

proton-cli     - Run Proton in a terminal
proton-config  - Change settings for Proton CLI!

The configuration file can be found in: {Style.BOLD}{HOME}/.config/proton-cli/config.json{Style.END}
The binary files can be found in: {Style.BOLD}{HOME}/.local/bin/{Style.END}
The local files can be found in: {Style.BOLD}{HOME}/.local/share/proton-cli{Style.END}

To uninstall this app simply use {Style.UNDERLINE}proton-config uninstall{Style.END}
""")
    elif arg == "copy":
        install()
        write_to_version()
    else:
        print("""
Usage: ./install [SUBCOMMAND]

Avaliable subcommands:
    copy  -  Only copy updated files to ~/.local/bin
""")
