import os
import requests
import zipfile
import tkinter as tk
from tkinter import messagebox, ttk
import shutil
import subprocess
import time

# Define directories and URLs
APPDATA_DIR = os.getenv('APPDATA')
MC_DIR = os.path.join(APPDATA_DIR, '.minecraft')
INSTALLER_DIR = os.path.join(os.path.dirname(__file__), 'mc-server-installer-directory')
FORGE_JAR = os.path.join(MC_DIR, 'versions', '1.20.1-forge-47.3.0', '1.20.1-forge-47.3.0.jar')
MODS_URL = 'https://flonetzt.duckdns.org/files/mods.zip'
DEFAULT_CONFIG_URL = 'https://flonetzt.duckdns.org/files/default-config.zip'
FORGE_INSTALLER_URL = 'https://flonetzt.duckdns.org/files/forge-installer.zip'
FORGE_INSTALLER_ZIP = os.path.join(INSTALLER_DIR, 'forge-installer.zip')
FORGE_INSTALLER_DIR = os.path.join(INSTALLER_DIR, 'forge-install')

# Create installer directory if it doesn't exist
if not os.path.exists(INSTALLER_DIR):
    os.makedirs(INSTALLER_DIR)

def download_file(url, local_path):
    response = requests.get(url, stream=True)
    total_size = int(response.headers.get('content-length', 0))
    downloaded_size = 0
    start_time = time.time()

    if total_size == 0:
        progress_var.set("Konnte die Dateigröße nicht ermitteln.")
        root.update_idletasks()
        return

    with open(local_path, 'wb') as file:
        for data in response.iter_content(chunk_size=8192):
            file.write(data)
            downloaded_size += len(data)
            progress = (downloaded_size / total_size) * 100
            elapsed_time = time.time() - start_time
            speed = downloaded_size / elapsed_time / (1024 * 1024)  # Speed in MB/s
            update_progress(progress, downloaded_size, total_size, speed)
            root.update_idletasks()  # Force the GUI to update during the download

def update_progress(progress, downloaded_size, total_size, speed):
    progress_var.set(f"Fortschritt: {int(progress)}% ({downloaded_size // (1024 * 1024)} / {total_size // (1024 * 1024)} MB) - {speed:.2f} MB/s")
    progress_bar['value'] = progress
    root.update_idletasks()

def extract_zip(zip_path, extract_to):
    with zipfile.ZipFile(zip_path, 'r') as zip_ref:
        for member in zip_ref.namelist():
            member_path = os.path.join(extract_to, member)
            if member.endswith('/'):
                os.makedirs(member_path, exist_ok=True)
            else:
                with zip_ref.open(member) as source, open(member_path, 'wb') as target:
                    shutil.copyfileobj(source, target)

def install_forge():
    if not os.path.exists(FORGE_JAR):
        if messagebox.askyesno("Forge-Installation", "Forge wurde nicht gefunden. Möchten Sie es installieren?"):
            progress_var.set("Lade Forge-Installer herunter...")
            root.update_idletasks()
            download_file(FORGE_INSTALLER_URL, FORGE_INSTALLER_ZIP)
            
            progress_var.set("Extrahiere Forge-Installer...")
            root.update_idletasks()
            extract_zip(FORGE_INSTALLER_ZIP, INSTALLER_DIR)
            
            java_path = os.path.join(FORGE_INSTALLER_DIR, 'Java', 'jre1.8.0_421', 'bin', 'javaw.exe')  # Use javaw.exe
            forge_jar = os.path.join(FORGE_INSTALLER_DIR, 'forge-installer.jar')

            if os.path.exists(java_path) and os.path.exists(forge_jar):
                try:
                    # Change working directory to the directory containing the forge installer
                    os.chdir(FORGE_INSTALLER_DIR)
                    
                    # Run the command using subprocess
                    result = subprocess.run([java_path, '-jar', forge_jar], capture_output=True, text=True)
                    
                    if result.returncode != 0:
                        messagebox.showerror("Fehler", f"Fehler beim Ausführen des Forge-Installers:\n{result.stderr}")
                    else:
                        messagebox.showinfo("Erfolg", "Forge wurde erfolgreich installiert.")
                except Exception as e:
                    messagebox.showerror("Fehler", f"Es ist ein Fehler aufgetreten: {e}")
            else:
                messagebox.showerror("Fehler", "Forge-Installer-Dateien fehlen.")
                return False
    else:
        messagebox.showinfo("Forge-Installation", "Forge ist bereits installiert.")
    return True

def install_update_mods():
    if messagebox.askyesno("Mods-Installation", "Möchten Sie die Mods installieren/aktualisieren?"):
        progress_var.set("Lade Mods herunter...")
        root.update_idletasks()
        
        mods_zip_path = os.path.join(INSTALLER_DIR, 'mods.zip')
        download_file(MODS_URL, mods_zip_path)
        
        mods_dir = os.path.join(MC_DIR, 'mods')
        if os.path.exists(mods_dir):
            shutil.rmtree(mods_dir)
        os.makedirs(mods_dir)
        
        progress_var.set("Extrahiere Mods...")
        root.update_idletasks()
        extract_zip(mods_zip_path, MC_DIR)

    if messagebox.askyesno("Standard-Konfiguration", "Möchten Sie die Standard-Konfiguration installieren/aktualisieren?"):
        progress_var.set("Lade Standard-Konfiguration herunter...")
        root.update_idletasks()
        default_config_zip_path = os.path.join(INSTALLER_DIR, 'default-config.zip')
        download_file(DEFAULT_CONFIG_URL, default_config_zip_path)
        progress_var.set("Extrahiere Standard-Konfiguration...")
        root.update_idletasks()
        extract_zip(default_config_zip_path, MC_DIR)
    
    messagebox.showinfo("Fertig", "Installation/Aktualisierung der Mods und der Standard-Konfiguration abgeschlossen.")
    cleanup_and_exit()

def install_config():
    progress_var.set("Lade Standard-Konfiguration herunter...")
    root.update_idletasks()
    default_config_zip_path = os.path.join(INSTALLER_DIR, 'default-config.zip')
    download_file(DEFAULT_CONFIG_URL, default_config_zip_path)
    
    progress_var.set("Extrahiere Standard-Konfiguration...")
    root.update_idletasks()
    extract_zip(default_config_zip_path, MC_DIR)
    
    messagebox.showinfo("Fertig", "Installation der Standard-Konfiguration abgeschlossen.")

def cleanup_and_exit():
    try:
        if os.path.exists(INSTALLER_DIR):
            shutil.rmtree(INSTALLER_DIR)
    except Exception as e:
        print(f"Cleanup failed: {e}")
    finally:
        root.destroy()

# Create GUI
root = tk.Tk()
root.title("Minecraft Installer")

# Maximize window
root.state('zoomed')

# Set background color and style
root.configure(bg='#2E2E2E')  # Dark gray background
progress_var = tk.StringVar()
progress_var.set("Starte...")
progress_label = tk.Label(root, textvariable=progress_var, font=('Helvetica', 16), bg='#2E2E2E', fg='white')
progress_label.pack(pady=20)

# Add Progress Bar
progress_bar = ttk.Progressbar(root, orient='horizontal', length=400, mode='determinate')
progress_bar.pack(pady=10)

# Add Install buttons
forge_button = tk.Button(root, text="Forge installieren", command=install_forge, font=('Helvetica', 14), bg='#4A4A4A', fg='white')
forge_button.pack(pady=10)

mods_button = tk.Button(root, text="Mods installieren", command=install_update_mods, font=('Helvetica', 14), bg='#4A4A4A', fg='white')
mods_button.pack(pady=10)

config_button = tk.Button(root, text="Standard-Konfiguration installieren", command=install_config, font=('Helvetica', 14), bg='#4A4A4A', fg='white')
config_button.pack(pady=10)

# Add Exit button
exit_button = tk.Button(root, text="Beenden und Verzeichnis löschen", command=cleanup_and_exit, font=('Helvetica', 14), bg='#4A4A4A', fg='white')
exit_button.pack(pady=10)

# Handle window close event
def on_closing():
    if messagebox.askokcancel("Beenden", "Möchten Sie das Programm wirklich beenden?"):
        cleanup_and_exit()

root.protocol("WM_DELETE_WINDOW", on_closing)

root.mainloop()
