# Instructions
# Get Python 3 (https://www.python.org/downloads/) (Install with PATH)
# pip install requests beautifulsoup4
# python .\lolroms_download.py "https://lolroms.com/Acorn/Archimedes"

import os
import re
import sys
from pathlib import Path
from urllib.parse import urljoin, urlparse, unquote

import requests
from bs4 import BeautifulSoup

ARCHIVE_EXTENSIONS = (
    ".flac",
    ".7z",
    ".chd",
)

session = requests.Session()

session.headers.update({
    "User-Agent": "LoLRoms Downloader/1.0",
    "X-LoLRoms-Token": "TransparentBanana"
})

def clean_url(text):
    m = re.search(r'https?://[^"\'> ]+', text)
    return m.group(0) if m else text
    print("URL:", repr(root_url))

def get_links(url):
    r = session.get(url, timeout=30)

    print("Status:", r.status_code)

    if r.status_code != 200:
        print(r.text[:2000])
        r.raise_for_status()

    html = r.text

    nav_end = html.lower().find("</nav>")

    if nav_end != -1:
        html = html[nav_end + 6:]

    soup = BeautifulSoup(html, "html.parser")

    links = []

    for a in soup.find_all("a", href=True):
        href = a.get("href")

        if href:
            links.append(urljoin(url, href))

    print(f"Found {len(links)} links")

    return links


def filename_from_url(url):
    return os.path.basename(urlparse(url).path)


def is_archive(url):
    path = urlparse(url).path.lower()
    return path.endswith(ARCHIVE_EXTENSIONS)


def download_file(url, output_dir):
    with session.get(url, stream=True, timeout=300) as r:
        r.raise_for_status()

        filename = get_filename(url, r)

        filename = re.sub(
            r'[<>:"/\\|?*]',
            '_',
            filename
        )

        output = output_dir / filename

        if output.exists():
            print(f"SKIP {filename}")
            return

        print(f"GET  {filename}")

        with open(output, "wb") as f:
            for chunk in r.iter_content(1024 * 1024):
                if chunk:
                    f.write(chunk)

def get_filename(url, response):
    cd = response.headers.get("Content-Disposition", "")

    m = re.search(
        r'filename\*=UTF-8\'\'([^;]+)|filename="?([^"]+)"?',
        cd,
        re.IGNORECASE
    )

    if m:
        return unquote(
            m.group(1) or m.group(2)
        )

    return (
        unquote(
            os.path.basename(
                urlparse(response.url).path
            )
        )
        or "download.bin"
    )


def main(root_url):
    root_url = clean_url(root_url)
    print("URL:", root_url)

    try:
        links = get_links(root_url)
    except Exception as e:
        print(f"Failed: {e}")
        return

    folder_name = (
        Path(urlparse(root_url).path).name
        or "downloads"
    )

    out_dir = Path(folder_name)
    out_dir.mkdir(exist_ok=True)

    visited_files = set()

    for link in links:
        if not is_archive(link):
            continue

        if link in visited_files:
            continue

        visited_files.add(link)

        download_file(link, out_dir)

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(
            "Usage:\n"
            "python download_sets.py "
            "https://lolroms.com/Atari/2600"
        )
        sys.exit(1)

    main(sys.argv[1])