# Copyright 2018 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from pathlib import Path
import argparse
import base64
import collections
import hashlib
import os
import re
import sys
import zipfile


def commonpath(path1, path2):
    ret = []
    for a, b in zip(path1.split(os.path.sep), path2.split(os.path.sep)):
        if a != b:
            break
        ret.append(a)
    return os.path.sep.join(ret)


def escape_filename_segment(segment):
    """Escapes a filename segment per https://www.python.org/dev/peps/pep-0427/#escaping-and-unicode"""
    return re.sub(r"[^\w\d.]+", "_", segment, re.UNICODE)


class WheelMaker(object):
    def __init__(self, name, version, build_tag, python_tag, abi, platform,
                 outfile=None, strip_path_prefixes=None):
        self._name = name
        self._version = version
        self._build_tag = build_tag
        self._python_tag = python_tag
        self._abi = abi
        self._platform = platform
        self._outfile = outfile
        self._strip_path_prefixes = strip_path_prefixes if strip_path_prefixes is not None else []

        self._distinfo_dir = (escape_filename_segment(self._name) + '-' +
                              escape_filename_segment(self._version) +
                              '.dist-info/')
        self._zipfile = None
        self._record = []

    def __enter__(self):
        self._zipfile = zipfile.ZipFile(self.filename(), mode="w",
                                        compression=zipfile.ZIP_DEFLATED)
        return self

    def __exit__(self, type, value, traceback):
        self._zipfile.close()
        self._zipfile = None

    def wheelname(self) -> str:
        components = [self._name, self._version]
        if self._build_tag:
            components.append(self._build_tag)
        components += [self._python_tag, self._abi, self._platform]
        return '-'.join(components) + '.whl'

    def filename(self) -> str:
        if self._outfile:
            return self._outfile
        return self.wheelname()

    def disttags(self):
        return ['-'.join([self._python_tag, self._abi, self._platform])]

    def distinfo_path(self, basename):
        return self._distinfo_dir + basename

    def _serialize_digest(self, hash):
        # https://www.python.org/dev/peps/pep-0376/#record
        # "base64.urlsafe_b64encode(digest) with trailing = removed"
        digest = base64.urlsafe_b64encode(hash.digest())
        digest = b'sha256=' + digest.rstrip(b'=')
        return digest

    def add_string(self, filename, contents):
        """Add given 'contents' as filename to the distribution."""
        if sys.version_info[0] > 2 and isinstance(contents, str):
            contents = contents.encode('utf-8', 'surrogateescape')
        self._zipfile.writestr(filename, contents)
        hash = hashlib.sha256()
        hash.update(contents)
        self._add_to_record(filename, self._serialize_digest(hash),
                            len(contents))

    def add_file(self, package_filename, real_filename):
        """Add given file to the distribution."""

        def arcname_from(name):
            # Always use unix path separators.
            normalized_arcname = name.replace(os.path.sep, '/')
            for prefix in self._strip_path_prefixes:
                if normalized_arcname.startswith(prefix):
                    return normalized_arcname[len(prefix):]

            return normalized_arcname

        if os.path.isdir(real_filename):
            directory_contents = os.listdir(real_filename)
            for file_ in directory_contents:
                self.add_file("{}/{}".format(package_filename, file_),
                              "{}/{}".format(real_filename, file_))
            return

        arcname = arcname_from(package_filename)

        self._zipfile.write(real_filename, arcname=arcname)
        # Find the hash and length
        hash = hashlib.sha256()
        size = 0
        with open(real_filename, 'rb') as f:
            while True:
                block = f.read(2 ** 20)
                if not block:
                    break
                hash.update(block)
                size += len(block)
        self._add_to_record(arcname, self._serialize_digest(hash), size)

    def add_wheelfile(self):
        """Write WHEEL file to the distribution"""
        # TODO(pstradomski): Support non-purelib wheels.
        wheel_contents = """\
Wheel-Version: 1.0
Generator: bazel-wheelmaker 1.0
Root-Is-Purelib: {}
""".format("true" if self._platform == "any" else "false")
        for tag in self.disttags():
            wheel_contents += "Tag: %s\n" % tag
        self.add_string(self.distinfo_path('WHEEL'), wheel_contents)

    def add_metadata(self, extra_headers, description, classifiers, python_requires,
                     requires, extra_requires):
        """Write METADATA file to the distribution."""
        # https://www.python.org/dev/peps/pep-0566/
        # https://packaging.python.org/specifications/core-metadata/
        metadata = []
        metadata.append("Metadata-Version: 2.1")
        metadata.append("Name: %s" % self._name)
        metadata.append("Version: %s" % self._version)
        metadata.extend(extra_headers)
        for classifier in classifiers:
            metadata.append("Classifier: %s" % classifier)
        if python_requires:
            metadata.append("Requires-Python: %s" % python_requires)
        for requirement in requires:
            metadata.append("Requires-Dist: %s" % requirement)

        extra_requires = sorted(extra_requires.items())
        for option, option_requires in extra_requires:
            metadata.append("Provides-Extra: %s" % option)
            for requirement in option_requires:
                metadata.append(
                    "Requires-Dist: %s; extra == '%s'" % (requirement, option))

        metadata = '\n'.join(metadata) + '\n\n'
        # setuptools seems to insert UNKNOWN as description when none is
        # provided.
        metadata += description if description else "UNKNOWN"
        metadata += "\n"
        self.add_string(self.distinfo_path('METADATA'), metadata)

    def add_recordfile(self):
        """Write RECORD file to the distribution."""
        record_path = self.distinfo_path('RECORD')
        entries = self._record + [(record_path, b'', b'')]
        entries.sort()
        contents = b''
        for filename, digest, size in entries:
            if sys.version_info[0] > 2 and isinstance(filename, str):
                filename = filename.encode('utf-8', 'surrogateescape')
            contents += b'%s,%s,%s\n' % (filename, digest, size)
        self.add_string(record_path, contents)

    def _add_to_record(self, filename, hash, size):
        size = str(size).encode('ascii')
        self._record.append((filename, hash, size))


def get_files_to_package(input_files):
    """Find files to be added to the distribution.

    input_files: list of pairs (package_path, real_path)
    """
    files = {}
    for package_path, real_path in input_files:
        files[package_path] = real_path
    return files


def resolve_version_stamp(version: str, volatile_status_stamp: Path, stable_status_stamp: Path) -> str:
    """Resolve workspace status stamps format strings found in the version string

    Args:
        version (str): The raw version represenation for the wheel (may include stamp variables)
        volatile_status_stamp (Path): The path to a volatile workspace status file
        stable_status_stamp (Path): The path to a stable workspace status file

    Returns:
        str: A resolved version string
    """
    lines = volatile_status_stamp.read_text().splitlines() + stable_status_stamp.read_text().splitlines()
    for line in lines:
        if not line:
            continue
        key, value = line.split(' ', maxsplit=1)
        stamp = "{" + key + "}"
        version = version.replace(stamp, value)

    return version


def parse_args() -> argparse.Namespace:
    parser = argparse.ArgumentParser(description='Builds a python wheel')
    metadata_group = parser.add_argument_group(
        "Wheel name, version and platform")
    metadata_group.add_argument('--name', required=True,
                                type=str,
                                help="Name of the distribution")
    metadata_group.add_argument('--version', required=True,
                                type=str,
                                help="Version of the distribution")
    metadata_group.add_argument('--build_tag', type=str, default='',
                                help="Optional build tag for the distribution")
    metadata_group.add_argument('--python_tag', type=str, default='py3',
                                help="Python version, e.g. 'py2' or 'py3'")
    metadata_group.add_argument('--abi', type=str, default='none')
    metadata_group.add_argument('--platform', type=str, default='any',
                                help="Target platform. ")

    output_group = parser.add_argument_group("Output file location")
    output_group.add_argument('--out', type=str, default=None,
                              help="Override name of ouptut file")
    output_group.add_argument('--name_file', type=Path,
                              help="A file where the canonical name of the "
                                   "wheel will be written")

    output_group.add_argument('--strip_path_prefix',
                              type=str,
                              action="append",
                              default=[],
                              help="Path prefix to be stripped from input package files' path. "
                                   "Can be supplied multiple times. "
                                   "Evaluated in order."
                              )

    wheel_group = parser.add_argument_group("Wheel metadata")
    wheel_group.add_argument(
        '--header', action='append',
        help="Additional headers to be embedded in the package metadata. "
             "Can be supplied multiple times.")
    wheel_group.add_argument('--classifier', action='append',
                             help="Classifiers to embed in package metadata. "
                                  "Can be supplied multiple times")
    wheel_group.add_argument('--python_requires',
                             help="Version of python that the wheel will work with")
    wheel_group.add_argument('--description_file',
                             help="Path to the file with package description")
    wheel_group.add_argument('--entry_points_file',
                             help="Path to a correctly-formatted entry_points.txt file")

    contents_group = parser.add_argument_group("Wheel contents")
    contents_group.add_argument(
        '--input_file', action='append',
        help="'package_path;real_path' pairs listing "
             "files to be included in the wheel. "
             "Can be supplied multiple times.")
    contents_group.add_argument(
        '--input_file_list', action='append',
        help='A file that has all the input files defined as a list to avoid the long command'
    )

    requirements_group = parser.add_argument_group("Package requirements")
    requirements_group.add_argument(
        '--requires', type=str, action='append',
        help="List of package requirements. Can be supplied multiple times.")
    requirements_group.add_argument(
        '--extra_requires', type=str, action='append',
        help="List of optional requirements in a 'requirement;option name'. "
             "Can be supplied multiple times.")

    build_group = parser.add_argument_group("Building requirements")
    build_group.add_argument(
        '--volatile_status_file', type=Path,
        help="Pass in the stamp info file for stamping"
    )
    build_group.add_argument(
        '--stable_status_file', type=Path,
        help="Pass in the stamp info file for stamping"
    )

    return parser.parse_args(sys.argv[1:])


def main() -> None:
    arguments = parse_args()

    if arguments.input_file:
        input_files = [i.split(';') for i in arguments.input_file]
    else:
        input_files = []

    if arguments.input_file_list:
        for input_file in arguments.input_file_list:
            with open(input_file) as _file:
                input_file_list = _file.read().splitlines()
            for _input_file in input_file_list:
                input_files.append(_input_file.split(';'))

    all_files = get_files_to_package(input_files)
    # Sort the files for reproducible order in the archive.
    all_files = sorted(all_files.items())

    strip_prefixes = [p for p in arguments.strip_path_prefix]

    if arguments.volatile_status_file and arguments.stable_status_file:
        version = resolve_version_stamp(arguments.version,
                                        arguments.volatile_status_file,
                                        arguments.stable_status_file)
    else:
        version = arguments.version

    with WheelMaker(name=arguments.name,
                    version=version,
                    build_tag=arguments.build_tag,
                    python_tag=arguments.python_tag,
                    abi=arguments.abi,
                    platform=arguments.platform,
                    outfile=arguments.out,
                    strip_path_prefixes=strip_prefixes
                    ) as maker:
        for package_filename, real_filename in all_files:
            maker.add_file(package_filename, real_filename)
        maker.add_wheelfile()

        description = None
        if arguments.description_file:
            if sys.version_info[0] == 2:
                with open(arguments.description_file,
                          'rt') as description_file:
                    description = description_file.read()
            else:
                with open(arguments.description_file, 'rt',
                          encoding='utf-8') as description_file:
                    description = description_file.read()

        extra_requires = collections.defaultdict(list)
        if arguments.extra_requires:
            for extra in arguments.extra_requires:
                req, option = extra.rsplit(';', 1)
                extra_requires[option].append(req)
        classifiers = arguments.classifier or []
        python_requires = arguments.python_requires or ""
        requires = arguments.requires or []
        extra_headers = arguments.header or []

        maker.add_metadata(extra_headers=extra_headers,
                           description=description,
                           classifiers=classifiers,
                           python_requires=python_requires,
                           requires=requires,
                           extra_requires=extra_requires)

        if arguments.entry_points_file:
            maker.add_file(maker.distinfo_path(
                "entry_points.txt"), arguments.entry_points_file)

        maker.add_recordfile()

        # Since stamping may otherwise change the target name of the
        # wheel, the canonical name (with stamps resolved) is written
        # to a file so consumers of the wheel can easily determine
        # the correct name.
        arguments.name_file.write_text(maker.wheelname())


if __name__ == '__main__':
    main()
