"""
Python build manager
Author: Shai Bennathan - shai.bennathan@gmail.com
(C) 2020
"""
import subprocess
import shutil
import datetime
import logging
from pykrete.packages import install_python_packages
from pykrete.args import environ
from pykrete.versioning import Formatting, make_python_root_version_file_path
from .build_manager import BuildManager


class PythonBuildManager(BuildManager):
    """Manages building a python package"""

    _logger = logging.getLogger(__name__)

    def _clean_distribution(self):
        """Removes previous distribution files"""
        self._logger.debug('Deleting previous distribution')
        shutil.rmtree('dist', ignore_errors=True)

    def _upload(self):
        """Uploads the package if self.upload is True"""
        install_python_packages('twine')
        self._make_pypirc()
        self._run_setup(
            'Uploading package...',
            'twine', '--project', self._project)

    def _build(self):
        """Performs the actual build using setup.py"""
        install_python_packages('setuptools', 'wheel')
        self._run_setup(
            'Building package...',
            'check', 'sdist', 'bdist_wheel')

    def _set_package_version(self):
        """Sets the package version in the project's version file"""
        version = Formatting(self._version).for_python
        self._logger.debug('Setting version to: %s', version)
        with open(make_python_root_version_file_path(self._project), 'w') as version_file:
            self._write_lines(version_file, self._make_version_file_lines(version))

    def _make_version_file_lines(self, version):
        """Makes the lines of version.py

        :return: The version file's lines
        """
        return [
            '"""',
            f'{self._project.title()} module version',
            'AUTO-GENERATED BY BUILD.PY',
            f'(C) {datetime.date.today().year}',
            '"""',
            '',
            f'__version__ = \'{version}\'',
            ''
        ]

    def _run_setup(self, message, *args):
        """Runs setup.py

        :param message: pre-run debug message
        :param args: setup.py argument
        """
        self._logger.debug(message)
        subprocess.check_call(['python', 'setup.py'] + list(args))

    def _make_pypirc(self):
        """Generates the pypirc file required for upload, from GitLab environment variables:
        username: PYPI_USER
        password: PYPI_PASSWORD
        """
        self._logger.debug('Prepping pypirc')
        path = environ('pypirc')
        with open(path if path else 'pypirc', 'w') as pypirc:
            self._write_lines(pypirc, self._make_pypirc_lines())

    @staticmethod
    def _write_lines(file, lines):
        file.writelines('\n'.join(lines) + '\n')

    @staticmethod
    def _make_pypirc_lines():
        return [
            '[distutils]',
            'index-servers =',
            '    pypi',
            '',
            '[pypi]',
            '    username: ' + environ('PYPI_USER', 'the Pypi repository user name'),
            '    password: ' + environ('PYPI_PASSWORD', 'the Pypi repository password/API-key'),
        ]
