# Test utilities for fetching & caching assets
#
# Copyright 2024 Red Hat, Inc.
#
# This work is licensed under the terms of the GNU GPL, version 2 or
# later.  See the COPYING file in the top-level directory.

import hashlib
import logging
import os
import subprocess
import sys
import unittest
import urllib.request
from time import sleep
from pathlib import Path
from shutil import copyfileobj


# Instances of this class must be declared as class level variables
# starting with a name "ASSET_". This enables the pre-caching logic
# to easily find all referenced assets and download them prior to
# execution of the tests.
class Asset:

    def __init__(self, url, hashsum):
        self.url = url
        self.hash = hashsum
        cache_dir_env = os.getenv('QEMU_TEST_CACHE_DIR')
        if cache_dir_env:
            self.cache_dir = Path(cache_dir_env, "download")
        else:
            self.cache_dir = Path(Path("~").expanduser(),
                                  ".cache", "qemu", "download")
        self.cache_file = Path(self.cache_dir, hashsum)
        self.log = logging.getLogger('qemu-test')

    def __repr__(self):
        return "Asset: url=%s hash=%s cache=%s" % (
            self.url, self.hash, self.cache_file)

    def _check(self, cache_file):
        if self.hash is None:
            return True
        if len(self.hash) == 64:
            hl = hashlib.sha256()
        elif len(self.hash) == 128:
            hl = hashlib.sha512()
        else:
            raise Exception("unknown hash type")

        # Calculate the hash of the file:
        with open(cache_file, 'rb') as file:
            while True:
                chunk = file.read(1 << 20)
                if not chunk:
                    break
                hl.update(chunk)

        return  hl.hexdigest()

    def valid(self):
        return self.cache_file.exists() and self._check(self.cache_file)

    def _wait_for_other_download(self, tmp_cache_file):
        # Another thread already seems to download the asset, so wait until
        # it is done, while also checking the size to see whether it is stuck
        try:
            current_size = tmp_cache_file.stat().st_size
            new_size = current_size
        except:
            if os.path.exists(self.cache_file):
                return True
            raise
        waittime = lastchange = 600
        while waittime > 0:
            sleep(1)
            waittime -= 1
            try:
                new_size = tmp_cache_file.stat().st_size
            except:
                if os.path.exists(self.cache_file):
                    return True
                raise
            if new_size != current_size:
                lastchange = waittime
                current_size = new_size
            elif lastchange - waittime > 90:
                return False

        self.log.debug("Time out while waiting for %s!", tmp_cache_file)
        raise

    def fetch(self):
        if not self.cache_dir.exists():
            self.cache_dir.mkdir(parents=True, exist_ok=True)

        if self.valid():
            self.log.debug("Using cached asset %s for %s",
                           self.cache_file, self.url)
            return str(self.cache_file)

        if os.environ.get("QEMU_TEST_NO_DOWNLOAD", False):
            raise Exception("Asset cache is invalid and downloads disabled")

        self.log.info("Downloading %s to %s...", self.url, self.cache_file)
        tmp_cache_file = self.cache_file.with_suffix(".download")

        for retries in range(3):
            try:
                with tmp_cache_file.open("xb") as dst:
                    with urllib.request.urlopen(self.url) as resp:
                        copyfileobj(resp, dst)
                break
            except FileExistsError:
                self.log.debug("%s already exists, "
                               "waiting for other thread to finish...",
                               tmp_cache_file)
                if self._wait_for_other_download(tmp_cache_file):
                    return str(self.cache_file)
                self.log.debug("%s seems to be stale, "
                               "deleting and retrying download...",
                               tmp_cache_file)
                tmp_cache_file.unlink()
                continue
            except Exception as e:
                self.log.error("Unable to download %s: %s", self.url, e)
                tmp_cache_file.unlink()
                raise

        try:
            # Set these just for informational purposes
            os.setxattr(str(tmp_cache_file), "user.qemu-asset-url",
                        self.url.encode('utf8'))
            os.setxattr(str(tmp_cache_file), "user.qemu-asset-hash",
                        self.hash.encode('utf8'))
        except Exception as e:
            self.log.debug("Unable to set xattr on %s: %s", tmp_cache_file, e)
            pass

        if not self._check(tmp_cache_file):
            tmp_cache_file.unlink()
            raise Exception("Hash of %s does not match %s" %
                            (self.url, self.hash))
        tmp_cache_file.replace(self.cache_file)

        self.log.info("Cached %s at %s" % (self.url, self.cache_file))
        return str(self.cache_file)

    def precache_test(test):
        log = logging.getLogger('qemu-test')
        log.setLevel(logging.DEBUG)
        handler = logging.StreamHandler(sys.stdout)
        handler.setLevel(logging.DEBUG)
        formatter = logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        handler.setFormatter(formatter)
        log.addHandler(handler)
        for name, asset in vars(test.__class__).items():
            if name.startswith("ASSET_") and type(asset) == Asset:
                log.info("Attempting to cache '%s'" % asset)
                asset.fetch()
        log.removeHandler(handler)

    def precache_suite(suite):
        for test in suite:
            if isinstance(test, unittest.TestSuite):
                Asset.precache_suite(test)
            elif isinstance(test, unittest.TestCase):
                Asset.precache_test(test)

    def precache_suites(path, cacheTstamp):
        loader = unittest.loader.defaultTestLoader
        tests = loader.loadTestsFromNames([path], None)

        with open(cacheTstamp, "w") as fh:
            Asset.precache_suite(tests)
