# 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.
# ==============================================================================
"""Setup for Tink package with pip."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import glob
import os
import posixpath
import shutil
import subprocess
import sys

from distutils import spawn
import setuptools
from setuptools.command import build_ext

here = os.path.dirname(os.path.abspath(__file__))


def _get_tink_version():
  """Parses the version number from VERSION file."""
  with open(os.path.join(here, 'VERSION')) as f:
    try:
      version_line = next(
          line for line in f if line.startswith('TINK_VERSION_LABEL'))
    except StopIteration:
      raise ValueError('Version not defined in python/VERSION')
    else:
      return version_line.split(' = ')[-1].strip('\n \'"')

# Check Bazel enviroment and set executable
if spawn.find_executable('bazelisk'):
  bazel = 'bazelisk'
elif spawn.find_executable('bazel'):
  bazel = 'bazel'
else:
  sys.stderr.write('Could not find bazel executable. Please install bazel to'
                   'compile the Tink Python package.')
  sys.exit(-1)

# Find the Protocol Compiler.
if 'PROTOC' in os.environ and os.path.exists(os.environ['PROTOC']):
  protoc = os.environ['PROTOC']
else:
  protoc = spawn.find_executable('protoc')


def _generate_proto(source):
  """Invokes the Protocol Compiler to generate a _pb2.py."""

  output = source.replace('.proto', '_pb2.py')

  if (not os.path.exists(output) or
      (os.path.exists(source) and
       os.path.getmtime(source) > os.path.getmtime(output))):
    print('Generating %s...' % output)

    if not os.path.exists(source):
      sys.stderr.write('Cannot find required file: %s\n' % source)
      sys.exit(-1)

    if protoc is None:
      sys.stderr.write(
          'protoc is not installed nor found in ../src.  Please compile it '
          'or install the binary package.\n')
      sys.exit(-1)

    protoc_command = [protoc, '-I.', '--python_out=.', source]
    if subprocess.call(protoc_command) != 0:
      sys.exit(-1)

for proto_file in glob.glob('tink/proto/*.proto'):
  _generate_proto(proto_file)


def _parse_requirements(path):
  with open(os.path.join(here, path)) as f:
    return [
        line.rstrip()
        for line in f
        if not (line.isspace() or line.startswith('#'))
    ]


def _patch_workspace(workspace_content):
  """Change inclusion of the other WORKSPACEs in Tink to be absolute.

  Setuptools builds in a temporary folder, therefore the relative paths can not
  be resolved. Instead we use the http_archives during the build.

  Args:
    workspace_content: The original tink/python WORKSPACE.
  Returns:
    The workspace_content using http_archive for tink_base and tink_cc.
  """
  # Add http_archive load
  workspace_lines = workspace_content.split('\n')
  http_archive_load = ('load("@bazel_tools//tools/build_defs/repo:http.bzl", '
                       '"http_archive")')
  workspace_content = '\n'.join([workspace_lines[0], http_archive_load] +
                                workspace_lines[1:])

  # Replace local with http archives
  base = ('local_repository(\n'
          '    name = "tink_base",\n'
          '    path = "..",\n'
          ')\n')

  cc = ('local_repository(\n'
        '    name = "tink_cc",\n'
        '    path = "../cc",\n'
        ')\n')

  base_http = (
      'http_archive(\n'
      '    name = "tink_base",\n'
      '    urls = ["https://github.com/google/tink/archive/master.zip"],\n'
      '    strip_prefix = "tink-master/",\n'
      ')\n')

  cc_http = (
      'http_archive(\n'
      '    name = "tink_cc",\n'
      '    urls = ["https://github.com/google/tink/archive/master.zip"],\n'
      '    strip_prefix = "tink-master/cc",\n'
      ')\n')

  workspace_content = workspace_content.replace(base, base_http)
  workspace_content = workspace_content.replace(cc, cc_http)
  return workspace_content


class BazelExtension(setuptools.Extension):
  """A C/C++ extension that is defined as a Bazel BUILD target."""

  def __init__(self, bazel_target, target_name=''):
    self.bazel_target = bazel_target
    self.relpath, self.target_name = (
        posixpath.relpath(bazel_target, '//').split(':'))
    if target_name:
      self.target_name = target_name
    ext_name = os.path.join(
        self.relpath.replace(posixpath.sep, os.path.sep), self.target_name)
    setuptools.Extension.__init__(self, ext_name, sources=[])


class BuildBazelExtension(build_ext.build_ext):
  """A command that runs Bazel to build a C/C++ extension."""

  def run(self):
    for ext in self.extensions:
      self.bazel_build(ext)
    build_ext.build_ext.run(self)

  def bazel_build(self, ext):
    # Change WORKSPACE to include tink_base and tink_cc from an archive
    with open('WORKSPACE', 'r') as f:
      workspace_contents = f.read()
    with open('WORKSPACE', 'w') as f:
      f.write(_patch_workspace(workspace_contents))

    if not os.path.exists(self.build_temp):
      os.makedirs(self.build_temp)

    bazel_argv = [
        bazel,
        'build',
        ext.bazel_target,
        '--compilation_mode=' + ('dbg' if self.debug else 'opt'),
    ]
    self.spawn(bazel_argv)
    ext_bazel_bin_path = os.path.join('bazel-bin', ext.relpath,
                                      ext.target_name + '.so')
    ext_dest_path = self.get_ext_fullpath(ext.name)
    ext_dest_dir = os.path.dirname(ext_dest_path)
    if not os.path.exists(ext_dest_dir):
      os.makedirs(ext_dest_dir)
    shutil.copyfile(ext_bazel_bin_path, ext_dest_path)

# TODO(kste): Parse these targets from the pybind folder.
bazel_modules = [
    BazelExtension('//tink/cc/pybind:import_helper', 'libimport_helper'),
    BazelExtension('//tink/cc/pybind:cc_gcp_kms_client'),
    BazelExtension('//tink/cc/pybind:cc_key_manager'),
    BazelExtension('//tink/cc/pybind:cc_tink_config'),
    BazelExtension('//tink/cc/pybind:python_file_object_adapter'),
    BazelExtension('//tink/cc/pybind:output_stream_adapter'),
    BazelExtension('//tink/cc/pybind:cc_streaming_aead_wrappers'),
    BazelExtension('//tink/cc/pybind:status_utils', 'libstatus_utils'),
    BazelExtension('//tink/cc/pybind:status'),
    BazelExtension('//tink/cc/pybind:status_example'),
    BazelExtension('//tink/cc/pybind:aead'),
    BazelExtension('//tink/cc/pybind:deterministic_aead'),
    BazelExtension('//tink/cc/pybind:streaming_aead'),
    BazelExtension('//tink/cc/pybind:hybrid_decrypt'),
    BazelExtension('//tink/cc/pybind:hybrid_encrypt'),
    BazelExtension('//tink/cc/pybind:mac'),
    BazelExtension('//tink/cc/pybind:public_key_sign'),
    BazelExtension('//tink/cc/pybind:public_key_verify'),
]

setuptools.setup(
    name='tink',
    version=_get_tink_version(),
    url='https://github.com/google/tink',
    description='A multi-language, cross-platform library that provides '
    'cryptographic APIs that are secure, easy to use correctly, '
    'and hard(er) to misuse.',
    author='Tink Developers',
    author_email='tink-users@googlegroups.com',
    long_description=open('README.md').read(),
    long_description_content_type='text/markdown',
    # Contained modules and scripts.
    packages=setuptools.find_packages(),
    install_requires=_parse_requirements('requirements.txt'),
    cmdclass=dict(build_ext=BuildBazelExtension),
    ext_modules=bazel_modules,
    zip_safe=False,
    # PyPI package information.
    classifiers=[
        'Programming Language :: Python :: 3.7',
        'Topic :: Software Development :: Libraries',
    ],
    license='Apache 2.0',
    keywords='tink cryptography',
)
