#!/usr/bin/env python3
#
# Copyright 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.

import os
import shutil
import subprocess
import sys
from distutils import cmd
from distutils import log

import setuptools
from setuptools.command.develop import develop
from setuptools.command.install import install

FRAMEWORK_DIR = 'acts_framework'
LOCAL_FRAMEWORK_DIR = '../acts/framework'

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

install_requires = ['soundfile']



def _setup_acts_framework(option, *args):
    """Locates and runs setup.py for the ACTS framework.

    Args:
        option: the option to use with setup.py, e.g. install, develop
        args: additional args for the command
    """
    acts_framework_dir = os.path.join(acts_tests_dir, FRAMEWORK_DIR)
    if not os.path.isdir(acts_framework_dir):
        log.info('Directory "%s" not found. Attempting to locate ACTS '
                 'framework through local repository.' % acts_framework_dir)
        acts_framework_dir = os.path.join(acts_tests_dir, LOCAL_FRAMEWORK_DIR)
        if not os.path.isdir(acts_framework_dir):
            log.error('Cannot install ACTS framework. Framework dir "%s" not '
                      'found.' % acts_framework_dir)
            exit(1)
    acts_setup_bin = os.path.join(acts_framework_dir, 'setup.py')
    if not os.path.isfile(acts_setup_bin):
        log.error('Cannot install ACTS framework. Setup script not found.')
        exit(1)
    command = [sys.executable, acts_setup_bin, option, *args]
    subprocess.check_call(command, cwd=acts_framework_dir)


class ActsContribInstall(install):
    """Custom installation of the acts_contrib package.

    Also installs the required ACTS framework via its own setup.py script.

    The installation requires the ACTS framework to exist under the
    "acts_framework" directory, at the same level of this setup script.
    Otherwise, it will attempt to locate the ACTS framework from the local
    repository.
    """
    def run(self):
        _setup_acts_framework('install')
        # Calling install.run() directly fails to install the dependencies as
        # listed in install_requires. Use install.do_egg_install() instead.
        # Ref: https://stackoverflow.com/questions/21915469
        self.do_egg_install()


class ActsContribDevelop(develop):
    """Custom installation of the acts_contrib package (in develop mode).

    See ActsContribInstall for more details.
    """
    def run(self):
        super().run()
        if self.uninstall:
            _setup_acts_framework('develop', '-u')
        else:
            _setup_acts_framework('develop')


class ActsContribInstallDependencies(cmd.Command):
    """Installs only required packages

    Installs all required packages for acts_contrib to work. Rather than using
    the normal install system which creates links with the python egg, pip is
    used to install the packages.
    """

    description = 'Install dependencies needed for acts_contrib packages.'
    user_options = []

    def initialize_options(self):
        pass

    def finalize_options(self):
        pass

    def run(self):
        install_args = [sys.executable, '-m', 'pip', 'install']
        subprocess.check_call(install_args + ['--upgrade', 'pip'])
        required_packages = self.distribution.install_requires

        for package in required_packages:
            self.announce('Installing %s...' % package, log.INFO)
            subprocess.check_call(install_args +
                                  ['-v', '--no-cache-dir', package])

        self.announce('Dependencies installed.')


class ActsContribUninstall(cmd.Command):
    """acts_contrib uninstaller.

    Uninstalls acts_contrib from the current version of python. This will
    attempt to import acts_contrib from any of the python egg locations. If it
    finds an import it will use the modules file location to delete it. This is
    repeated until acts_contrib can no longer be imported and thus is
    uninstalled.
    """

    description = 'Uninstall acts_contrib from the local machine.'
    user_options = []

    def initialize_options(self):
        pass

    def finalize_options(self):
        pass

    def uninstall_acts_contrib_module(self, acts_contrib_module):
        """Uninstalls acts_contrib from a module.

        Args:
            acts_contrib_module: The acts_contrib module to uninstall.
        """
        for acts_contrib_install_dir in acts_contrib_module.__path__:
            self.announce('Deleting acts_contrib from: %s'
                          % acts_contrib_install_dir, log.INFO)
            shutil.rmtree(acts_contrib_install_dir)

    def run(self):
        """Entry point for the uninstaller."""
        # Remove the working directory from the python path. This ensures that
        # Source code is not accidentally targeted.
        our_dir = os.path.abspath(os.path.dirname(__file__))
        if our_dir in sys.path:
            sys.path.remove(our_dir)

        if os.getcwd() in sys.path:
            sys.path.remove(os.getcwd())

        try:
            import acts_contrib as acts_contrib_module
        except ImportError:
            self.announce('acts_contrib is not installed, nothing to uninstall.',
                          level=log.ERROR)
            return

        while acts_contrib_module:
            self.uninstall_acts_contrib_module(acts_contrib_module)
            try:
                del sys.modules['acts_contrib']
                import acts_contrib as acts_contrib_module
            except ImportError:
                acts_contrib_module = None

        self.announce('Finished uninstalling acts_contrib.')

        # Uninstall the ACTS framework
        _setup_acts_framework('uninstall')


def main():
    os.chdir(acts_tests_dir)
    packages = setuptools.find_packages(include=('acts_contrib*',))
    setuptools.setup(name='acts_contrib',
                     version='0.9',
                     description='Android Comms Test Suite',
                     license='Apache2.0',
                     packages=packages,
                     include_package_data=True,
                     install_requires=install_requires,
                     cmdclass={
                         'install': ActsContribInstall,
                         'develop': ActsContribDevelop,
                         'install_deps': ActsContribInstallDependencies,
                         'uninstall': ActsContribUninstall
                     },
                     url="http://www.android.com/")


if __name__ == '__main__':
    main()
