import datetime
import io
from pathlib import Path
import re
import shutil
import time
import zipfile

from selenium import webdriver


class DownloadError(Exception):
    pass

def apk_from_xapk(xapk_data, app_id):
    """This is necessary because on apkpure.com uses a custom package format xapk for some apps."""
    with io.BytesIO(xapk_data) as stream:
        with zipfile.ZipFile(stream) as zip:
            with zip.open(f"{app_id}.apk", 'r') as f:
                return f.read()

def get(app_id):
    options = webdriver.FirefoxOptions()
    options.add_argument("--headless")

    profile = webdriver.FirefoxProfile()
    profile.set_preference("browser.download.folderList", 2)
    profile.set_preference("browser.helperApps.alwaysAsk.force", False)
    profile.set_preference("browser.download.manager.showWhenStarting",False)
    profile.set_preference("browser.download.dir", "/tmp/tempapk/")
    profile.set_preference("browser.helperApps.neverAsk.saveToDisk", "application/vnd.android.package-archive, application/xapk-package-archive" )

    try:
        shutil.rmtree('/tmp/tempapk/')
    except FileNotFoundError:
        pass

    with webdriver.Firefox(options=options, firefox_profile=profile) as driver:
        driver.get(f"https://apkpure.com/_/{app_id}/download?from=details")
        dl_page = driver.page_source
    
        t = datetime.datetime.now()
        while True:
            p = Path('/tmp/tempapk/')
            try:
                p = list(p.iterdir())
            except FileNotFoundError:
                raise DownloadError
            if len(p) == 1:
                break
            elif datetime.datetime.now()-t > datetime.timedelta(seconds=60):
                raise DownloadError
            time.sleep(1)

    with open(p[0], 'rb') as f:
        apk_data = f.read()
    shutil.rmtree('/tmp/tempapk/')

    # check if xapk
    match = re.search(r'_v.+_apkpure.com.(x?)apk', dl_page)
    xapk = bool(match.groups()[0])

    if xapk:
        apk_data = apk_from_xapk(apk_data, app_id)

    return apk_data
