import os
import re
from . import apiPack
from flask import request, jsonify, send_file, redirect, url_for, abort
from config import PACKS_FOLDER, IMG_ALLOWED_MIME
from PIL import Image
from io import BytesIO
import base64
import json
from .source import Modrinth, CurseForge


@apiPack.route("/<id>", methods=["GET"])
def getPack(id):
    if not os.path.exists(f"{PACKS_FOLDER}/{id}/packfile.json"):
        return jsonify({"status": "error", "message": "pack not found"}), 404

    pack = {}
    with open(f"{PACKS_FOLDER}/{id}/packfile.json") as fp:
        pack = json.load(fp)
        pack["_id"] = id
        fp.close()

    return jsonify(pack)


@apiPack.route("/<id>/image", methods=["GET"])
def getPackImage(id):
    if not os.path.exists(f"{PACKS_FOLDER}/{id}/packicon.png"):
        return redirect(url_for("static", filename="defaulticon.png"))

    with open(f"{PACKS_FOLDER}/{id}/packicon.png", mode="rb") as fp:
        f = BytesIO(fp.read())
        return send_file(f, mimetype="image/png")


@apiPack.route("/<id>/image/edit", methods=["POST"])
def editPackImage(id):
    image_string = request.json.get("image")
    image_mime = request.json.get("mimetype")
    if image_string == None:
        return jsonify({"status": "error", "message": "no image provided"})
    if image_mime == None or image_mime not in IMG_ALLOWED_MIME:
        return jsonify({"status": "error", "message": "wrong image format"})

    image_data = base64.b64decode(
        re.sub("^data:image/.+;base64,", "", request.json.get("image"))
    )

    image = Image.open(BytesIO(image_data))
    image = image.resize((512, 512), Image.Resampling.LANCZOS)
    image.save(
        f"{PACKS_FOLDER}/{id}/packicon.png",
        "png",
    )

    return jsonify(
        {
            "status": "ok",
            "message": "image updated",
        }
    )


@apiPack.route("/<id>/mod/add", methods=["POST"])
def addMod(id):
    source = request.json.get("source", None)
    slug = request.json.get("slug", None)
    version = request.json.get("version", None)
    pack = {}
    mod = {}

    if not os.path.exists(f"{PACKS_FOLDER}/{id}/packfile.json"):
        return jsonify({"status": "error", "message": "pack not found"})
    with open(f"{PACKS_FOLDER}/{id}/packfile.json") as fp:
        pack = json.load(fp)
        fp.close()
    mod_loader = pack.get("modloader").lower()
    game_version = pack.get("version")

    if not source:
        return jsonify({"status": "error", "message": "mod source is required"})
    if not slug:
        return jsonify({"status": "error", "message": "mod slug is required"})

    for mod in pack["mods"]:
        if mod.get("slug") == slug:
            return jsonify({"status": "error", "message": "mod already exists"})

    if source == "Modrinth":
        mod = Modrinth.getModrinthMod(slug, version, mod_loader, game_version)
    elif source == "CurseForge":
        mod = CurseForge.getCurseForgeMod(slug, version, mod_loader, game_version)

    if mod.get("status") != "ok":
        return jsonify({"status": "error", "message": mod.get("message")})

    pack["modpackVersion"] += 1
    pack["mods"].append(mod.get("mod"))
    with open(f"{PACKS_FOLDER}/{id}/packfile.json", mode="w", encoding="utf-8") as fp:
        json.dump(pack, fp)
        fp.close()

    return jsonify(
        {
            "status": "ok",
            "message": f"mod {mod.get("mod").get('title')} ({slug}) has been added",
            "mod": mod.get("mod"),
        }
    )


@apiPack.route("/<id>/mod/<slug>/delete", methods=["GET"])
def deleteMod(id, slug):
    pack = {}
    with open(f"{PACKS_FOLDER}/{id}/packfile.json") as fp:
        pack = json.load(fp)
        fp.close()

    for mod in pack.get("mods"):
        if mod.get("slug") == slug:
            pack["mods"].remove(mod)
            pack["modpackVersion"] += 1
            if os.path.exists(
                f"{PACKS_FOLDER}/{id}/mods/{mod.get('file').get('filename')}"
            ):
                os.remove(f"{PACKS_FOLDER}/{id}/mods/{mod.get('file').get('filename')}")

    with open(f"{PACKS_FOLDER}/{id}/packfile.json", mode="w", encoding="utf-8") as fp:
        json.dump(pack, fp)
        fp.close()

    return jsonify(
        {
            "status": "ok",
            "message": f"mod {slug} has been removed",
        }
    )


@apiPack.route("/<id>/mods/delete", methods=["POST"])
def deleteModBulk(id):
    pack = {}
    slugs = request.json

    with open(f"{PACKS_FOLDER}/{id}/packfile.json") as fp:
        pack = json.load(fp)
        fp.close()

    for slug in slugs:
        for mod in pack.get("mods"):
            if mod.get("slug") == slug:
                pack["mods"].remove(mod)
                pack["modpackVersion"] += 1
                if os.path.exists(
                    f"{PACKS_FOLDER}/{id}/mods/{mod.get('file').get('filename')}"
                ):
                    os.remove(
                        f"{PACKS_FOLDER}/{id}/mods/{mod.get('file').get('filename')}"
                    )

    with open(f"{PACKS_FOLDER}/{id}/packfile.json", mode="w", encoding="utf-8") as fp:
        json.dump(pack, fp)
        fp.close()

    return jsonify(
        {
            "status": "ok",
            "message": f"mods has been removed",
        }
    )