"""Check a project and backend by attempting to build using PEP 517 hooks.
"""
import argparse
import io
import logging
import os
from os.path import isfile, join as pjoin
import shutil
from subprocess import CalledProcessError
import sys
import tarfile
from tempfile import mkdtemp
import zipfile

from .colorlog import enable_colourful_output
from .compat import TOMLDecodeError, toml_load
from .envbuild import BuildEnvironment
from .wrappers import Pep517HookCaller

log = logging.getLogger(__name__)


def check_build_sdist(hooks, build_sys_requires):
    with BuildEnvironment() as env:
        try:
            env.pip_install(build_sys_requires)
            log.info('Installed static build dependencies')
        except CalledProcessError:
            log.error('Failed to install static build dependencies')
            return False

        try:
            reqs = hooks.get_requires_for_build_sdist({})
            log.info('Got build requires: %s', reqs)
        except Exception:
            log.error('Failure in get_requires_for_build_sdist', exc_info=True)
            return False

        try:
            env.pip_install(reqs)
            log.info('Installed dynamic build dependencies')
        except CalledProcessError:
            log.error('Failed to install dynamic build dependencies')
            return False

        td = mkdtemp()
        log.info('Trying to build sdist in %s', td)
        try:
            try:
                filename = hooks.build_sdist(td, {})
                log.info('build_sdist returned %r', filename)
            except Exception:
                log.info('Failure in build_sdist', exc_info=True)
                return False

            if not filename.endswith('.tar.gz'):
                log.error(
                    "Filename %s doesn't have .tar.gz extension", filename)
                return False

            path = pjoin(td, filename)
            if isfile(path):
                log.info("Output file %s exists", path)
            else:
                log.error("Output file %s does not exist", path)
                return False

            if tarfile.is_tarfile(path):
                log.info("Output file is a tar file")
            else:
                log.error("Output file is not a tar file")
                return False

        finally:
            shutil.rmtree(td)

        return True


def check_build_wheel(hooks, build_sys_requires):
    with BuildEnvironment() as env:
        try:
            env.pip_install(build_sys_requires)
            log.info('Installed static build dependencies')
        except CalledProcessError:
            log.error('Failed to install static build dependencies')
            return False

        try:
            reqs = hooks.get_requires_for_build_wheel({})
            log.info('Got build requires: %s', reqs)
        except Exception:
            log.error('Failure in get_requires_for_build_sdist', exc_info=True)
            return False

        try:
            env.pip_install(reqs)
            log.info('Installed dynamic build dependencies')
        except CalledProcessError:
            log.error('Failed to install dynamic build dependencies')
            return False

        td = mkdtemp()
        log.info('Trying to build wheel in %s', td)
        try:
            try:
                filename = hooks.build_wheel(td, {})
                log.info('build_wheel returned %r', filename)
            except Exception:
                log.info('Failure in build_wheel', exc_info=True)
                return False

            if not filename.endswith('.whl'):
                log.error("Filename %s doesn't have .whl extension", filename)
                return False

            path = pjoin(td, filename)
            if isfile(path):
                log.info("Output file %s exists", path)
            else:
                log.error("Output file %s does not exist", path)
                return False

            if zipfile.is_zipfile(path):
                log.info("Output file is a zip file")
            else:
                log.error("Output file is not a zip file")
                return False

        finally:
            shutil.rmtree(td)

        return True


def check(source_dir):
    pyproject = pjoin(source_dir, 'pyproject.toml')
    if isfile(pyproject):
        log.info('Found pyproject.toml')
    else:
        log.error('Missing pyproject.toml')
        return False

    try:
        with io.open(pyproject, 'rb') as f:
            pyproject_data = toml_load(f)
        # Ensure the mandatory data can be loaded
        buildsys = pyproject_data['build-system']
        requires = buildsys['requires']
        backend = buildsys['build-backend']
        backend_path = buildsys.get('backend-path')
        log.info('Loaded pyproject.toml')
    except (TOMLDecodeError, KeyError):
        log.error("Invalid pyproject.toml", exc_info=True)
        return False

    hooks = Pep517HookCaller(source_dir, backend, backend_path)

    sdist_ok = check_build_sdist(hooks, requires)
    wheel_ok = check_build_wheel(hooks, requires)

    if not sdist_ok:
        log.warning('Sdist checks failed; scroll up to see')
    if not wheel_ok:
        log.warning('Wheel checks failed')

    return sdist_ok


def main(argv=None):
    log.warning('pep517.check is deprecated. '
                'Consider switching to https://pypi.org/project/build/')

    ap = argparse.ArgumentParser()
    ap.add_argument(
        'source_dir',
        help="A directory containing pyproject.toml")
    args = ap.parse_args(argv)

    enable_colourful_output()

    ok = check(args.source_dir)

    if ok:
        print(ansi('Checks passed', 'green'))
    else:
        print(ansi('Checks failed', 'red'))
        sys.exit(1)


ansi_codes = {
    'reset': '\x1b[0m',
    'bold': '\x1b[1m',
    'red': '\x1b[31m',
    'green': '\x1b[32m',
}


def ansi(s, attr):
    if os.name != 'nt' and sys.stdout.isatty():
        return ansi_codes[attr] + str(s) + ansi_codes['reset']
    else:
        return str(s)


if __name__ == '__main__':
    main()
