import os
import gzip
import requests
from tqdm import tqdm

# -----------------------------
# DEVICE + FEED CONFIGURATION
# -----------------------------

# IMPORTANT: Ensure all URLs include ending slashes !

DEVICES = {
    "ar750s": {
        "feeds": {
            "1": {
                "name": "glinet_core",
                "url": "https://fw.gl-inet.com/releases/v22.03.4/kmod-4.3.2/ar750s/",
                "out": "kmod-4.3.2/ar750s"
            },
            "2": {
                "name": "glinet_gli_pub",
                "url": "https://fw.gl-inet.com/releases/v22.03.4/packages-4.2/ath79/glinet/",
                "out": "packages-4.2/ath79/glinet"
            },
            "3": {
                "name": "glinet_gli_packages",
                "url": "https://fw.gl-inet.com/releases/v22.03.4/packages-4.2/ath79/packages/",
                "out": "packages-4.2/ath79/packages"
            }
        }
    },

    "x750(v2)": {
        "feeds": {
            "1": {
                "name": "glinet_core",
                "url": "https://fw.gl-inet.com/releases/v22.03.4/kmod-4.3.2/x750/",
                "out": "kmod-4.3.2/x750"
            },
            "2": {
                "name": "glinet_gli_pub",
                "url": "https://fw.gl-inet.com/releases/v22.03.4/packages-4.2/ath79/glinet/",
                "out": "packages-4.2/ath79/glinet"
            },
            "3": {
                "name": "glinet_gli_packages",
                "url": "https://fw.gl-inet.com/releases/v22.03.4/packages-4.2/ath79/packages/",
                "out": "packages-4.2/ath79/packages"
            }
        }
    },

    "xe300": {
        "feeds": {
            "1": {
                "name": "glinet_core",
                "url": "https://fw.gl-inet.com/releases/v22.03.4/kmod-4.3.2/xe300/",
                "out": "kmod-4.3.2/xe300"
            },
            "2": {
                "name": "glinet_gli_pub",
                "url": "https://fw.gl-inet.com/releases/v22.03.4/packages-4.2/ath79/glinet/",
                "out": "packages-4.2/ath79/glinet"
            },
            "3": {
                "name": "glinet_gli_packages",
                "url": "https://fw.gl-inet.com/releases/v22.03.4/packages-4.2/ath79/packages/",
                "out": "packages-4.2/ath79/packages"
            }
        }
    },

    "mt1300": {
        "feeds": {
            "1": {
                "name": "glinet_core",
                "url": "https://fw.gl-inet.com/releases/v22.03.4/kmod-4.3.2/mt1300/",
                "out": "kmod-4.3.2/mt1300"
            },
            "2": {
                "name": "glinet_gli_pub",
                "url": "https://fw.gl-inet.com/releases/v22.03.4/packages-4.x/mt7621/glinet/",
                "out": "packages-4.x/mt7621/glinet"
            },
            "3": {
                "name": "glinet_gli_packages",
                "url": "https://fw.gl-inet.com/releases/v22.03.4/packages-4.2/mipsel_24kc/packages/",
                "out": "packages-4.2/mipsel_24kc/packages"
            }
        }
    },

    "mt300n-v2": {
        "feeds": {
            "1": {
                "name": "glinet_core",
                "url": "https://fw.gl-inet.com/releases/v22.03.4/kmod-4.3.2/mt300n-v2/",
                "out": "kmod-4.3.2/mt300n-v2"
            },
            "2": {
                "name": "glinet_gli_pub",
                "url": "https://fw.gl-inet.com/releases/v22.03.4/packages-4.x/mt7628/glinet/",
                "out": "packages-4.x/mt7628/glinet"
            },
            "3": {
                "name": "glinet_gli_packages",
                "url": "https://fw.gl-inet.com/releases/v22.03.4/packages-4.2/mipsel_24kc/packages/",
                "out": "packages-4.2/mipsel_24kc/packages"
            }
        }
    },
	
    "ar300m(16)": {
        "feeds": {
            "1": {
                "name": "glinet_core",
                "url": "https://fw.gl-inet.com/releases/v22.03.4/kmod-4.3.2/ar300m/",
                "out": "kmod-4.3.2/ar300m"
            },
            "2": {
                "name": "glinet_gli_pub",
                "url": "https://fw.gl-inet.com/releases/v22.03.4/packages-4.2/ath79/glinet/",
                "out": "packages-4.2/ath79/glinet"
            },
            "3": {
                "name": "glinet_gli_packages",
                "url": "https://fw.gl-inet.com/releases/v22.03.4/packages-4.2/ath79/packages/",
                "out": "packages-4.2/ath79/packages"
            }
        }
    }

}

# -----------------------------
# DEVICE SELECTION
# -----------------------------
print("Device:")
print("1 = AR750S")
print("2 = X750(v2)")
print("3 = XE300")
print("4 = MT1300")
print("5 = MT300N-V2")
print("6 = AR300M(16)")

device_choice = input("#: ").strip()

DEVICE_MAP = {
    "1": "ar750s",
    "2": "x750(v2)",
    "3": "xe300",
    "4": "mt1300",
    "5": "mt300n-v2",
    "6": "ar300m(16)"
}

if device_choice not in DEVICE_MAP:
    print("Invalid device. Exiting.")
    exit(1)

DEVICE = DEVICE_MAP[device_choice]

# -----------------------------
# FEED SELECTION
# -----------------------------
print("\nFeed to download:")
print("1 = glinet_core (kernel modules)")
print("2 = glinet_gli_pub (GL.iNet public packages)")
print("3 = glinet_gli_packages (generic OpenWrt packages)")

feed_choice = input("#: ").strip()

if feed_choice not in DEVICES[DEVICE]["feeds"]:
    print("Invalid feed. Exiting.")
    exit(1)

FEED_URL = DEVICES[DEVICE]["feeds"][feed_choice]["url"]
OUTPUT_DIR = DEVICES[DEVICE]["feeds"][feed_choice]["out"]

print(f"\nSelected device: {DEVICE}")
print(f"Selected feed: {DEVICES[DEVICE]['feeds'][feed_choice]['name']}")
print(f"Feed URL: {FEED_URL}")
print(f"Output directory: {OUTPUT_DIR}\n")

# -----------------------------
# Download Packages.gz
# -----------------------------
pkg_index_url = FEED_URL + "Packages.gz"
os.makedirs(OUTPUT_DIR, exist_ok=True)
pkg_index_path = os.path.join(OUTPUT_DIR, "Packages.gz")

print(f"Downloading index: {pkg_index_url}")
r = requests.get(pkg_index_url)
if r.status_code != 200:
    raise RuntimeError(f"Failed to download Packages.gz: HTTP {r.status_code}")

with open(pkg_index_path, "wb") as f:
    f.write(r.content)

# -----------------------------
# Parse Packages.gz
# -----------------------------
with gzip.open(pkg_index_path, "rt", encoding="utf-8") as f:
    lines = f.readlines()

files = []
for line in lines:
    if line.startswith("Filename: "):
        filename = line.split("Filename: ")[1].strip()
        files.append(filename)

print(f"Found {len(files)} packages")

# -----------------------------
# Download each .ipk
# -----------------------------
total_files = len(files)
current_index = 0

for filename in files:
    current_index += 1
    url = FEED_URL + filename
    local_path = os.path.join(OUTPUT_DIR, filename)

    # Skip existing files
    if os.path.exists(local_path):
        print(f"Skipping (exists) ({current_index}/{total_files}): {filename}")
        continue

    os.makedirs(os.path.dirname(local_path), exist_ok=True)

    print(f"Downloading ({current_index}/{total_files}): {filename} ", end="", flush=True)
    response = requests.get(url, stream=True)
    if response.status_code != 200:
        print(f"Failed: {url} (HTTP {response.status_code})")
        continue

    total = int(response.headers.get("content-length", 0))

    with open(local_path, "wb") as f, tqdm(
        total=total,
        unit="B",
        unit_scale=True,
        unit_divisor=1024,
        desc="",
		leave=False,
    ) as bar:
        for chunk in response.iter_content(chunk_size=8192):
            if chunk:
                f.write(chunk)
                bar.update(len(chunk))

print("Done.")