import os
import subprocess
import json

# List of required libraries
required_libraries = ["requests", "shutil"]

# Check and install required libraries
for library in required_libraries:
    try:
        __import__(library)
    except ImportError:
        print(f"Installing {library}...")
        subprocess.check_call(["pip", "install", library])

# Now you can continue with the rest of your script
import requests
import shutil
from zipfile import ZipFile

# Constants
MANIFEST_URL = "https://launchermeta.mojang.com/mc/game/version_manifest.json"
MINECRAFT_DIR = os.path.expanduser("~\\AppData\\Roaming\\.minecraft")
VERSIONS_DIR = os.path.join(MINECRAFT_DIR, "versions")
ASSETS_DIR = os.path.join(MINECRAFT_DIR, "assets")

# Function to extract DLL files from JAR
def extract_dlls(jar_path, natives_dir):
    with ZipFile(jar_path, 'r') as zip_ref:
        for file_info in zip_ref.infolist():
            if file_info.filename.endswith(".dll"):
                # Extract DLLs directly into natives folder
                dll_filename = os.path.basename(file_info.filename)
                dll_path = os.path.join(natives_dir, dll_filename)
                with zip_ref.open(file_info) as dll_file, open(dll_path, "wb") as output_file:
                    shutil.copyfileobj(dll_file, output_file)

# Retrieve version manifest
response = requests.get(MANIFEST_URL)
data = response.json()
minecraft_ver = data['latest']['release']

# Check if a newer version is available
versions = os.listdir(VERSIONS_DIR) if os.path.exists(VERSIONS_DIR) else []
if minecraft_ver not in versions:
    print(f"Updating to Minecraft {minecraft_ver}...")

    # Get JSON for the latest release version
    version_info_url = f"https://launchermeta.mojang.com/mc/game/version_manifest.json"
    response = requests.get(version_info_url)
    version_data = response.json()

    # Find the URL for the latest version
    for version in version_data['versions']:
        if version['id'] == minecraft_ver:
            download_url = version['url']
            break

    # Download the latest version's JSON
    response = requests.get(download_url)
    version_json = response.json()

    # Create the version directory if it doesn't exist
    version_dir = os.path.join(VERSIONS_DIR, minecraft_ver)
    os.makedirs(version_dir, exist_ok=True)
    print(f"Version directory: {version_dir}")

    # Download the client JAR
    jar_url = version_json['downloads']['client']['url']
    response = requests.get(jar_url)
    jar_path = os.path.join(version_dir, f"{minecraft_ver}.jar")
    print(f"Downloading JAR to: {jar_path}")
    with open(jar_path, 'wb') as f:
        f.write(response.content)

    # Create the natives folder
    natives_dir = os.path.join(version_dir, "natives")
    os.makedirs(natives_dir, exist_ok=True)
    print(f"Natives directory: {natives_dir}")

    # Download and extract native libraries from natives-windows.jar
    for library in version_json.get("libraries", []):
        if "natives-windows" in library.get("name", ""):
            natives_url = library["downloads"]["artifact"]["url"]
            if "natives-windows.jar" in natives_url:
                natives_path = os.path.join(version_dir, os.path.basename(natives_url))
                print(f"Downloading natives JAR to: {natives_path}")
                response = requests.get(natives_url)
                with open(natives_path, 'wb') as f:
                    f.write(response.content)
                extract_dlls(natives_path, natives_dir)
                os.remove(natives_path)

    # Download and store assets
    asset_index_url = version_json['assetIndex']['url']
    response = requests.get(asset_index_url)
    asset_index_data = response.json()

    # Create assets directory if it doesn't exist
    assets_objects_dir = os.path.join(ASSETS_DIR, "objects")
    os.makedirs(assets_objects_dir, exist_ok=True)

    # Download and store asset files with correct subdirectory structure
    for asset_key, asset_info in asset_index_data['objects'].items():
        asset_hash = asset_info['hash']
        asset_url = f"https://resources.download.minecraft.net/{asset_hash[:2]}/{asset_hash}"
        asset_path = os.path.join(assets_objects_dir, asset_hash[:2], asset_hash)

        if not os.path.exists(asset_path):
            # Create the subdirectories as needed
            subdirs = [assets_objects_dir, asset_hash[:2]]
            os.makedirs(os.path.join(ASSETS_DIR, "objects", asset_hash[:2]), exist_ok=True)

            print(f"Downloading asset: {asset_key}...")
            response = requests.get(asset_url)
            with open(asset_path, 'wb') as f:
                f.write(response.content)

    # Extract the major release number from minecraft_ver
    major_version = '.'.join(minecraft_ver.split('.')[:2])

    # Construct the JSON data
    minecraft_json_data = {
        "id": minecraft_ver,
        "family": major_version,  # Set family to the major release number
        "time": version_json["releaseTime"],
        "releaseTime": version_json["releaseTime"],
        "type": "release",
        "mainClass": "net.minecraft.client.main.Main",
        "minimumLauncherVersion": 21,
        "tlauncherVersion": 0,
        "libraries": version_json["libraries"],
        "downloads": version_json["downloads"],
        "assetIndex": version_json["assetIndex"],
        "assets": version_json["assets"],
        "arguments": version_json["arguments"],
        "javaVersion": version_json["javaVersion"],
        "logging": version_json["logging"]
    }

    # Create the JSON file in the version directory
    json_path = os.path.join(version_dir, f"{minecraft_ver}.json")
    with open(json_path, "w") as json_file:
        json.dump(minecraft_json_data, json_file, indent=2)

    print(f"Minecraft {minecraft_ver} is now updated!")

else:
    print(f"You already have the latest version of Minecraft ({minecraft_ver}).")

# Cleanup old versions if needed
# Note: This part is optional and can be adjusted based on your preferences.
older_versions = [version for version in versions if version != minecraft_ver]
for old_version in older_versions:
    shutil.rmtree(os.path.join(VERSIONS_DIR, old_version))
    print(f"Removed old version: {old_version}")