#!/usr/bin/env python3
#
# Copyright (C) 2017 The Android Open Source Project
#
# 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.
#
"""Installs VNDK snapshot under prebuilts/vndk/v{version}."""

import argparse
import glob
import logging
import os
import re
import shutil
import subprocess
import sys
import tempfile
import textwrap

import utils

from check_gpl_license import GPLChecker
from gen_buildfiles import GenBuildFile

ANDROID_BUILD_TOP = utils.get_android_build_top()
PREBUILTS_VNDK_DIR = utils.join_realpath(ANDROID_BUILD_TOP, 'prebuilts/vndk')


def start_branch(build):
    branch_name = 'update-' + (build or 'local')
    logging.info('Creating branch {branch} in {dir}'.format(
        branch=branch_name, dir=os.getcwd()))
    utils.check_call(['repo', 'start', branch_name, '.'])


def remove_old_snapshot(install_dir):
    logging.info('Removing any old files in {}'.format(install_dir))
    for file in glob.glob('{}/*'.format(install_dir)):
        try:
            if os.path.isfile(file):
                os.unlink(file)
            elif os.path.isdir(file):
                shutil.rmtree(file)
        except Exception as error:
            logging.error('Error: {}'.format(error))
            sys.exit(1)


def install_snapshot(branch, build, local_dir, install_dir, temp_artifact_dir):
    """Installs VNDK snapshot build artifacts to prebuilts/vndk/v{version}.

    1) Fetch build artifacts from Android Build server or from local_dir
    2) Unzip build artifacts

    Args:
      branch: string or None, branch name of build artifacts
      build: string or None, build number of build artifacts
      local_dir: string or None, local dir to pull artifacts from
      install_dir: string, directory to install VNDK snapshot
      temp_artifact_dir: string, temp directory to hold build artifacts fetched
        from Android Build server. For 'local' option, is set to None.
    """
    artifact_pattern = 'android-vndk-*.zip'

    if branch and build:
        artifact_dir = temp_artifact_dir
        os.chdir(temp_artifact_dir)
        logging.info('Fetching {pattern} from {branch} (bid: {build})'.format(
            pattern=artifact_pattern, branch=branch, build=build))
        utils.fetch_artifact(branch, build, artifact_pattern)

        manifest_pattern = 'manifest_{}.xml'.format(build)
        logging.info('Fetching {file} from {branch} (bid: {build})'.format(
            file=manifest_pattern, branch=branch, build=build))
        utils.fetch_artifact(branch, build, manifest_pattern,
                             utils.MANIFEST_FILE_NAME)

        os.chdir(install_dir)
    elif local_dir:
        logging.info('Fetching local VNDK snapshot from {}'.format(local_dir))
        artifact_dir = local_dir

    artifacts = glob.glob(os.path.join(artifact_dir, artifact_pattern))
    for artifact in artifacts:
        logging.info('Unzipping VNDK snapshot: {}'.format(artifact))
        utils.check_call(['unzip', '-qn', artifact, '-d', install_dir])

        # rename {install_dir}/{arch}/include/out/soong/.intermediates
        for soong_intermediates_dir in glob.glob(install_dir + '/*/include/' + utils.SOONG_INTERMEDIATES_DIR):
            generated_headers_dir = soong_intermediates_dir.replace(
                utils.SOONG_INTERMEDIATES_DIR,
                utils.GENERATED_HEADERS_DIR
            )
            os.rename(soong_intermediates_dir, generated_headers_dir)

def gather_notice_files(install_dir):
    """Gathers all NOTICE files to a common NOTICE_FILES directory."""

    common_notices_dir = utils.NOTICE_FILES_DIR_PATH
    logging.info('Creating {} directory to gather all NOTICE files...'.format(
        common_notices_dir))
    os.makedirs(common_notices_dir)
    for arch in utils.get_snapshot_archs(install_dir):
        notices_dir_per_arch = os.path.join(arch, utils.NOTICE_FILES_DIR_NAME)
        if os.path.isdir(notices_dir_per_arch):
            for notice_file in glob.glob(
                    '{}/**'.format(notices_dir_per_arch), recursive=True):
                if os.path.isfile(notice_file):
                    rel_path = os.path.relpath(notice_file, notices_dir_per_arch)
                    target_path = os.path.join(common_notices_dir, rel_path)
                    if not os.path.isfile(target_path):
                        os.makedirs(os.path.dirname(target_path), exist_ok=True)
                        shutil.copy(notice_file, target_path)
            shutil.rmtree(notices_dir_per_arch)


def post_processe_files_if_needed(vndk_version):
    """Renames vndkcore.libraries.txt and vndksp.libraries.txt
    files to have version suffix.
    Create empty vndkproduct.libraries.txt file if not exist.

    Args:
      vndk_version: int, version of VNDK snapshot
    """
    def add_version_suffix(file_name):
        logging.info('Rename {} to have version suffix'.format(file_name))
        target_files = glob.glob(
            os.path.join(utils.CONFIG_DIR_PATH_PATTERN, file_name))
        for target_file in target_files:
            name, ext = os.path.splitext(target_file)
            os.rename(target_file, name + '.' + str(vndk_version) + ext)
    def create_empty_file_if_not_exist(file_name):
        target_dirs = glob.glob(utils.CONFIG_DIR_PATH_PATTERN)
        for dir in target_dirs:
            path = os.path.join(dir, file_name)
            if os.path.isfile(path):
                continue
            logging.info('Creating empty file: {}'.format(path))
            open(path, 'a').close()

    files_to_add_version_suffix = ('vndkcore.libraries.txt',
                                   'vndkprivate.libraries.txt')
    files_to_create_if_not_exist = ('vndkproduct.libraries.txt',)
    for file_to_rename in files_to_add_version_suffix:
        add_version_suffix(file_to_rename)
    for file_to_create in files_to_create_if_not_exist:
        create_empty_file_if_not_exist(file_to_create)


def update_buildfiles(buildfile_generator):
    # To parse json information, read and generate arch android.bp using
    # generate_android_bp() first.
    logging.info('Generating Android.bp files...')
    buildfile_generator.generate_android_bp()

    logging.info('Generating root Android.bp file...')
    buildfile_generator.generate_root_android_bp()

    logging.info('Generating common/Android.bp file...')
    buildfile_generator.generate_common_android_bp()

def copy_owners(root_dir, install_dir):
    path = os.path.dirname(__file__)
    shutil.copy(os.path.join(root_dir, path, 'OWNERS'), install_dir)

def check_gpl_license(license_checker):
    try:
        license_checker.check_gpl_projects()
    except ValueError as error:
        logging.error('***CANNOT INSTALL VNDK SNAPSHOT***: {}'.format(error))
        raise


def commit(branch, build, version):
    logging.info('Making commit...')
    utils.check_call(['git', 'add', '.'])
    message = textwrap.dedent("""\
        Update VNDK snapshot v{version} to build {build}.

        Taken from branch {branch}.""").format(
        version=version, branch=branch, build=build)
    utils.check_call(['git', 'commit', '-m', message])


def run(vndk_version, branch, build_id, local, use_current_branch, remote,
        verbose):
    ''' Fetch and updtate the VNDK snapshots

    Args:
      vndk_version: int, VNDK snapshot version to install.
      branch: string, Branch to pull build from.
      build: string, Build number to pull.
      local: string, Fetch local VNDK snapshot artifacts from specified local
             directory instead of Android Build server.
      use-current-branch: boolean, Perform the update in the current branch.
                          Do not repo start.
      remote: string, Remote name to fetch and check if the revision of VNDK
              snapshot is included in the source to conform GPL license.
      verbose: int, Increase log output verbosity.
    '''
    local_path = None
    if local:
        local_path = os.path.abspath(os.path.expanduser(local))

    if local_path:
        if build_id or branch:
            raise ValueError(
                'When --local option is set, --branch or --build cannot be '
                'specified.')
        elif not os.path.isdir(local_path):
            raise RuntimeError(
                'The specified local directory, {}, does not exist.'.format(
                    local_path))
    else:
        if not (build_id and branch):
            raise ValueError(
                'Please provide both --branch and --build or set --local '
                'option.')

    install_dir = os.path.join(PREBUILTS_VNDK_DIR, 'v{}'.format(vndk_version))
    if not os.path.isdir(install_dir):
        raise RuntimeError(
            'The directory for VNDK snapshot version {ver} does not exist.\n'
            'Please request a new git project for prebuilts/vndk/v{ver} '
            'before installing new snapshot.'.format(ver=vndk_version))

    utils.set_logging_config(verbose)
    root_dir = os.getcwd()
    os.chdir(install_dir)

    if not use_current_branch:
        start_branch(build_id)

    remove_old_snapshot(install_dir)
    os.makedirs(utils.COMMON_DIR_PATH)

    temp_artifact_dir = None
    if not local_path:
        temp_artifact_dir = tempfile.mkdtemp()

    try:
        install_snapshot(branch, build_id, local_path, install_dir,
                         temp_artifact_dir)
        gather_notice_files(install_dir)
        post_processe_files_if_needed(vndk_version)

        buildfile_generator = GenBuildFile(install_dir, vndk_version)
        update_buildfiles(buildfile_generator)

        copy_owners(root_dir, install_dir)

        if not local_path and not branch.startswith('android'):
            license_checker = GPLChecker(install_dir, ANDROID_BUILD_TOP,
                                         buildfile_generator.modules_with_restricted_lic,
                                         temp_artifact_dir, remote)
            check_gpl_license(license_checker)
            logging.info(
                'Successfully updated VNDK snapshot v{}'.format(vndk_version))
    except Exception as error:
        logging.error('FAILED TO INSTALL SNAPSHOT: {}'.format(error))
        raise
    finally:
        if temp_artifact_dir:
            logging.info(
                'Deleting temp_artifact_dir: {}'.format(temp_artifact_dir))
            shutil.rmtree(temp_artifact_dir)

    if not local_path:
        commit(branch, build_id, vndk_version)
        logging.info(
            'Successfully created commit for VNDK snapshot v{}'.format(
                vndk_version))

    logging.info('Done.')


def get_args():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        'vndk_version',
        type=utils.vndk_version_int,
        help='VNDK snapshot version to install, e.g. "{}".'.format(
            utils.MINIMUM_VNDK_VERSION))
    parser.add_argument('-b', '--branch', help='Branch to pull build from.')
    parser.add_argument('--build', help='Build number to pull.')
    parser.add_argument(
        '--local',
        help=('Fetch local VNDK snapshot artifacts from specified local '
              'directory instead of Android Build server. '
              'Example: --local=/path/to/local/dir'))
    parser.add_argument(
        '--use-current-branch',
        action='store_true',
        help='Perform the update in the current branch. Do not repo start.')
    parser.add_argument(
        '--remote',
        default='aosp',
        help=('Remote name to fetch and check if the revision of VNDK snapshot '
              'is included in the source to conform GPL license. default=aosp'))
    parser.add_argument(
        '-v',
        '--verbose',
        action='count',
        default=0,
        help='Increase output verbosity, e.g. "-v", "-vv".')
    return parser.parse_args()


def main():
    """Program entry point."""
    args = get_args()
    run(args.vndk_version, args.branch, args.build, args.local,
        args.use_current_branch, args.remote, args.verbose)


if __name__ == '__main__':
    main()
