#!/bin/python
import os
import sys
import requests
from shutil import rmtree
import zipfile

os.system("")

print("\033[32m█| █|█|  █|    █|█|  █|█|  █|    █|\033[0m")
print("\033[32m█|█| █|  █|    █|██| █|█|  █|    █|\033[0m")
print("\033[32m██|  █|  █|    █|█|█|█|█|  █|    █|\033[0m")
print("\033[32m█|█| █|  █|█|  █|█| ██|█|  █|█|  █|\033[0m")
print("\033[32m█| █|█████|█████|█|  █|█████|█████|\033[0m")
print("\033[32mMinecraft Kujnuj instalační skript \033[0m")
print("")


def modpack_get():
    if not os.path.exists(".VERSION"):
        return "Žádný", ""
    with open(".VERSION", "r") as f:
        return f.readline(), f.readline()


def modpack_set(modid, version):
    with open(".VERSION", "w") as f:
        f.write(modid+"\n")
        f.write(version+"\n")


def download(src, dest):
    r = requests.get(src, headers=useragent)
    with open(dest, "wb") as f:
        for chunk in r.iter_content(chunk_size=65535):
            f.write(chunk)


def fetch(array, folder):
    if not os.path.isdir(folder):
        os.mkdir(folder)
    for item in array:
        file = os.path.basename(item)
        progress("count", "fetch", f"{folder}\n{file}")
        if not os.path.exists(folder+"/"+file):
            download(item, folder+"/"+file)


def extract(webpath, folder):
    progress("count", "extract", folder)
    download(webpath, ".part.zip")
    if not zipfile.is_zipfile(".part.zip"):
        dialog_msgbox("MAGRPACK - Error", f"ERROR: Soubor {webpath} není zip soubor!")
        os.remove(".part.zip")
        return
    with zipfile.ZipFile(".part.zip") as f:
        f.extractall(folder)
    os.remove(".part.zip")


def override_file(webpath, file):
    progress("count", "override file", file)
    download(webpath, file)


def override_line(line, file):  # "options.txt": [["maxFps:120", "maxFps:60"]]
    progress("count", "override line", f"{file}\n{line[0]}")
    if not type(line) is list:
        dialog_msgbox("MAGRPACK - Error", f"ERROR: {file}: není list")
        return
    if len(line) < 2:
        dialog_msgbox("MAGRPACK - Error", f"ERROR: {file}: kratší než 2")
        return
    if len(line) == 2:
        line.append(1)
    if not os.path.isfile(file):
        dialog_msgbox("MAGRPACK - Error", f"ERROR: {file} neexistuje")
        return
    s = ""
    with open(file, "r") as f:
        s = f.read()
    s = s.replace(line[0], line[1], line[2])
    with open(file, "w") as f:
        f.write(s)


def override_lines(lines, file):
    for line in lines:
        override_line(line, file)


def progress(op, arg="", arg2=1, me={"val": {}, "max": {}}):
    if op == "clear":  # arg: title
        me["val"] = {}
        me["max"] = {}
        me["tit"] = arg
        me["msg"] = ""
    elif op == "set":  # arg: tag; arg2: max;
        me["val"][arg] = 0
        me["max"][arg] = arg2
    elif op == "msg":
        me["msg"] = arg
    elif op == "count":  # arg: tag; arg2: msg;
        me["val"][arg] += 1
        me["msg"] = arg2
    tags = []
    s = 0
    m = 0
    for t in me["val"]:
        s += me["val"][t]
        m += me["max"][t]
        tags.append(t)
        tags.append(f"~ {me['val'][t]} / {me['max'][t]}")
    if m == 0:  # prevent division by zero
        m = 1
    dialog_progress(me["tit"], me["msg"], str(int(s / m * 100)), tags)


def install(spec):
    # TODO: os.path.splitroot

    # setup counters
    progress("clear", "MAGRPACK - Instalace "+spec["name"])
    if "extract" in spec:
        progress("set", "extract", len(spec["extract"]))
    if "fetch" in spec:
        x = 0
        for k in spec["fetch"]:
            x += len(spec["fetch"][k])
        progress("set", "fetch", x)
    if "override" in spec:
        if "file" in spec["override"]:
            progress("set", "override file", len(spec["override"]["file"]))
        if "line" in spec["override"]:
            x = 0
            for k in spec["override"]["line"]:
                x += len(spec["override"]["line"][k])
            progress("set", "override line", x)

    # do the installation
    if "extract" in spec:
        for k in spec["extract"]:
            extract(spec["extract"][k], k)
    if "fetch" in spec:
        for k in spec["fetch"]:
            fetch(spec["fetch"][k], k)
    if "override" in spec:
        if "file" in spec["override"]:
            for k in spec["override"]["file"]:
                override_file(spec["override"]["file"][k], k)
        if "line" in spec["override"]:
            for k in spec["override"]["line"]:
                override_lines(spec["override"]["line"][k], k)

    progress("msg", "Vytvářím .VERSION soubor")
    modpack_set(spec["id"], spec["version"])
    dialog_msgbox("MAGRPACK - Instalace", f"Modpack {spec['version']} úspěšně nainstalován!")


def uninstall():
    if not dialog_yesno("MAGRPACK - Ostranění", "Tato akce nejde vrátit zpět!\nOpravdu si přejete nadobro vymazat všechny módy?", ["--defaultno"]):
        print("Nic neprovedeno")
        return
    print("Maži mods")
    rmtree("mods")
    os.mkdir("mods")
    if dialog_yesno("MAGRPACK - Odstranění", "Chcete vymazat i configy?", ["--defaultno"]):
        print("Maži config")
        rmtree("config")
        os.mkdir("config")
        os.remove("options.txt")
    dialog_info("MAGRPACK - Ostranění", "Maži verze soubor")
    if os.path.exists("INSTALACE.txt"):
        os.remove("INSTALACE.txt")
    if os.path.exists(".VERSION"):
        os.remove(".VERSION")
    dialog_msgbox("MAGRPACK - Odstranění", "Úspěšně vymazáno")


def packinfo(modid):
    dialog_info("MAGRPACK - Informace", "Stahuji modpack info...")
    try:
        spec = requests.get(upstream+"spec/"+modid+".json", headers=useragent).json()  # noqa: E501
    except Exception as e:
        dialog_msgbox("MAGRPACK - Error", "Modpack nenalezen, možná neexistuje, nebo je neplatný:\n"+str(e))
        return
    while True:
        print("hello!!")
        info = f"""{spec["name"]}
- {spec["author"]} [{spec["website"]}]
- {spec["loader"]} [{spec["version"]}]
{spec["description"]}"""
        if not dialog_yesno("MAGRPACK - Informace", info, ["--no-label", "Zpátky", "--yes-label", "Instalovat"]):
            return
        if modpack_get()[0] != "Žádný":
            if not dialog_yesno("MAGRPACK - Instalace", "Detekován modpack. Ve složce máte módy, které mohou narušit fungování modpacku. Přejete si přesto pokračovat? (Instalátor nebude pokoušet přepisovat soubory)", ["--defaultno"]):  # noqa: E501
                continue
        install(spec)
        return


def selectpack():
    dialog_info("MAGRPACK - Instalace", "Stahuji seznam modpacků...")
    seznam = requests.get(upstream+"packlist.txt", headers=useragent).text.splitlines()  # noqa: E501
    while True:
        ok, tag = dialog_menu("MAGRPACK - Instalace", "Vyberte modpack: ", seznam, ["--cancel-label", "Zpátky", "--ok-label", "Info"])
        if not ok:
            return
        packinfo(seznam[int(tag)])


def dialog_dialog(args):
    dialog = "./dialog" if os.name == "posix" else "dialog.exe"
    childr, childw = os.pipe()
    pid = os.fork()
    if pid == 0:  # child
        try:
            os.close(childr)  # dont need reading
            os.dup2(childw, 2)  # pipe stderr to parent
            os.execv(dialog, args)
        except Exception as e:
            print(e)
            os._exit(127)
        os._exit(126)  # should not happen
    # parent
    os.close(childw)  # dont need writing
    retinfo = os.waitpid(pid, 0)[1]
    with os.fdopen(childr, "r") as f:
        output = f.read()
    if os.WIFEXITED(retinfo):
        exitcode = os.WEXITSTATUS(retinfo)
    else:
        exitcode = 127
    return exitcode, output


def dialog_menu(title, text, tagitem: dict, options=[]):
    args = ["--no-lines", "--no-tags", "--cr-wrap", "--title", title]
    args.extend(options)
    args.extend(["--menu", text, "0", "0", "0"])
    xx = 0
    for k in tagitem:
        if type(tagitem) is dict:
            args.append(str(k))
            args.append(str(tagitem[k]))
        else:
            args.append(str(xx))
            args.append(str(k))
            xx += 1
    ret, out = dialog_dialog(args)
    return ret == 0, out.rstrip("\r\n\t ")


def dialog_yesno(title, text, options=[]):
    args = ["--no-lines", "--cr-wrap", "--title", title]
    args.extend(options)
    args.extend(["--yesno", text, "0", "0"])
    ret, _ = dialog_dialog(args)
    return ret == 0


def dialog_msgbox(title, text, options=[]):
    args = ["--no-lines", "--cr-wrap", "--title", title, *options, "--msgbox", text, "0", "0"]  # noqa: E501
    ret, _ = dialog_dialog(args)
    return ret == 0


def dialog_info(title, text, options=[]):
    args = ["--no-lines", "--cr-wrap", "--title", title, *options, "--infobox", text, "0", "0"]  # noqa: E501
    ret, _ = dialog_dialog(args)
    return ret == 0


# tagitem: ["mods", 1, ...]; -X => X%; 5 => Done
def dialog_progress(title, text, percent, tagitems, options=[]):
    args = ["--no-lines", "--cr-wrap", "--title", title, *options, "--mixedgauge", text, "0", "0", percent, *tagitems]  # noqa: E501
    ret, _ = dialog_dialog(args)
    return ret == 0


def diagnose():
    modcount = 0
    if os.path.isdir("mods"):
        for thing in os.listdir("mods"):
            if thing.endswith(".jar"):
                modcount += 1
    dialog_msgbox("MAGRPACK - Diagnostika",
        "Verze Skriptu: MAGRPACK 3.4.1\n"
        +"Detekovaný Modpack: "+str(modpack_get())+"\n"
        +"Instalační Cesta: "+str(os.getcwd())+"\n"
        +"Počet modů v mods složce: "+str(modcount)+"\n"
        +"Upstream: "+str(upstream)+"\n"
        +"Autor: honzapkcz")

# path bootstrap

useragent = {"User-Agent": "Kujnuj/3.0.0 (honzapkcz)"}
upstream = "https://hbmy.eu/modpack/"


def bootstrap_move(path):
    print("Přesouvám do: "+path)
    os.rename(sys.argv[0], os.path.normpath(path+"/magrpack.py"))
    os.chdir(os.path.normpath(path+"/magrpack.py"))
    print("OK Přesunuto.")


def bootstrap_1():
    if os.path.exists(".magrpack"):
        print("Soubor .magrpack nalezen, přeskakuji setup.")
        return
    elif os.getcwd().find(".minecraft") != -1:
        print("Instalátor je v minecraft složce, přeskakuji setup.")
        return

    print("Instalátor není v .minecraft složce!")
    mcpath = ""
    if os.name == "posix" and os.path.isdir(os.path.expanduser("~/.minecraft")):  # noqa: E501
        mcpath = os.path.expanduser("~/.minecraft")
    if os.name == "posix" and os.path.isdir(os.path.expanduser("~/Library/Application Support/minecraft")):  # noqa: E501
        mcpath = os.path.expanduser("~/Library/Application Support/minecraft")
    if os.name == "nt" and os.path.isdir(os.path.expandvars("%appdata%/.minecraft")):  # noqa: E501
        mcpath = os.path.expandvars("%appdata%/.minecraft")

    if mcpath == "":
        print("Instalátor nenašel .minecraft složku.")
    else:
        print("Instalátor našel .minecraft složku: "+mcpath)
    print("Chcete nechat instalátor v této složce [n], přesunout ho [p] nebo zadat jinou .minecraft cestu [z]?")  # noqa: E501
    usin = ""
    while not usin.lower() in ["n", "p", "z"]:
        usin = input("[n/p/z] ")
        if usin.lower() == "p" and mcpath == "":
            usin = "z"
    if usin == "n":
        print("OK Nechávám.")
        with open(".magrpack", "w") as f:
            f.write("{}\n")
    elif usin == "z":
        print("Napište cestu vaší minecraft složky: ")
        while True:
            mcpath = os.path.expanduser(os.path.expandvars(input("[kam?] ")))
            if os.path.isdir(mcpath):
                break
            print("Složka neexistuje!")
        bootstrap_move(mcpath)
    elif usin == "p":
        bootstrap_move(mcpath)

# dialog bootstrap


bootstrap_1()

if os.name == "posix" and not os.path.exists("dialog"):
    print("Dialog nenalezen, stahuji...")
    download(upstream+"dialog", "dialog")
    mode = os.stat("dialog").st_mode
    mode |= (mode & 0o444) >> 2
    os.chmod("dialog", mode)
if os.name == "nt" and not os.path.exists("dialog.exe"):
    print("Dialog.exe nenalezen, stahuji...")
    download(upstream+"dialog.exe", "dialog.exe")

with open(".magrpack", "w") as f:
    f.write("{}\n")

print("Bootstrap dokončen.")

spec = False  # requests.get(upstream+"kujnuj.json", headers=useragent).json()
modcount = 0
if os.path.isdir("mods"):
    for thing in os.listdir("mods"):
        if thing.endswith(".jar"):
            modcount += 1
if os.path.exists(".VERSION"):
    f = open(".VERSION", "r")
    modpack = f.readline()
    f.close()
elif os.path.exists("INSTALACE.txt"):
    modpack = "KUJNUJ Manuální Instalace"
elif modcount > 0:
    modpack = "Neznámý"


while True:
    ok, tag = dialog_menu("MAGRPACK", "Nainstalovaný Modpack: "+modpack_get()[0]+"\nDostupné akce: ", {
        "i": "Instalovat Modpack",
        "r": "Odstranit modpack",
        "d": "Diagnostika",
        "x": "Odejít"
    }, ["--no-cancel"])  # noqa: E501

    if tag == "i":
        selectpack()
    elif tag == "r":
        uninstall()
    elif tag == "d":
        diagnose()
    elif tag == "x":
        print("\033[32m[Konec]\033[0m")
        break
