#!/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.
from distutils import cmd
from distutils import log
import subprocess
import os
import shutil
import setuptools
from setuptools.command import test
import sys

install_requires = [
    'backoff',
    'dlipower',
    # Future needs to have a newer version that contains urllib.
    'future>=0.16.0',
    'grpcio',
    'mobly>=1.10.0',
    # Latest version of mock (4.0.0b) causes a number of compatibility issues with ACTS unit tests
    # b/148695846, b/148814743
    'mock==3.0.5',
    'Monsoon',
    # paramiko-ng is needed vs paramiko as currently paramiko does not support
    # ed25519 ssh keys, which is what Fuchsia uses.
    'paramiko-ng',
    'protobuf>=3.14.0',
    'pylibftdi',
    'pynacl==1.4.0',
    'pyserial',
    'pyyaml>=5.1',
    'requests',
    'retry',
    'scapy',
    'usbinfo',
    'xlsxwriter',
    'zeroconf'
]

versioned_deps = {
    'numpy': 'numpy',
    'scipy': 'scipy'
}

# numpy and scipy version matrix per:
# https://docs.scipy.org/doc/scipy/reference/toolchain.html
if sys.version_info < (3, 8):
    versioned_deps['numpy'] = 'numpy<1.22'
    versioned_deps['scipy'] = 'scipy<1.8'
if sys.version_info < (3, 7):
    versioned_deps['numpy'] = 'numpy<1.20'
    versioned_deps['scipy'] = 'scipy<1.6'
    versioned_deps['typing_extensions'] = 'typing_extensions==4.1.1'
if sys.version_info < (3, 6):
    versioned_deps['numpy'] = 'numpy<1.19'
    versioned_deps['scipy'] = 'scipy<1.5'

install_requires += list(versioned_deps.values())

if sys.version_info < (3, ):
    install_requires.append('enum34')
    install_requires.append('statistics')
    # "futures" is needed for py2 compatibility and it only works in 2.7
    install_requires.append('futures')
    install_requires.append('py2-ipaddress')
    install_requires.append('subprocess32')

DEV_PACKAGES = ['shiv']

framework_dir = os.path.dirname(os.path.realpath(__file__))


class PyTest(test.test):
    """Class used to execute unit tests using PyTest. This allows us to execute
    unit tests without having to install the package.
    """

    def finalize_options(self):
        test.test.finalize_options(self)
        self.test_args = ['-x', "tests"]
        self.test_suite = True

    def run_tests(self):
        test_path = os.path.join(framework_dir,
                                 '../tests/meta/ActsUnitTest.py')
        result = subprocess.Popen('python3 %s' % test_path,
                                  stdout=sys.stdout,
                                  stderr=sys.stderr,
                                  shell=True)
        result.communicate()
        sys.exit(result.returncode)


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

    Installs all required packages for acts 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 to run on this machine.'
    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 ActsUninstall(cmd.Command):
    """Acts uninstaller.

    Uninstalls acts from the current version of python. This will attempt to
    import acts 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 can no longer be imported and thus is uninstalled.
    """

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

    def initialize_options(self):
        pass

    def finalize_options(self):
        pass

    def uninstall_acts_module(self, acts_module):
        """Uninstalls acts from a module.

        Args:
            acts_module: The acts module to uninstall.
        """
        for acts_install_dir in acts_module.__path__:
            self.announce('Deleting acts from: %s' % acts_install_dir,
                          log.INFO)
            shutil.rmtree(acts_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.
        if framework_dir in sys.path:
            sys.path.remove(framework_dir)

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

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

        while acts_module:
            self.uninstall_acts_module(acts_module)
            try:
                del sys.modules['acts']
                import acts as acts_module
            except ImportError:
                acts_module = None

        self.announce('Finished uninstalling acts.')


def main():
    scripts = [
        os.path.join('acts', 'bin', 'act.py'),
        os.path.join('acts', 'bin', 'monsoon.py')
    ]
    # cd to framework directory so the correct package namespace is found
    os.chdir(framework_dir)
    setuptools.setup(name='acts',
                     version='0.9',
                     description='Android Comms Test Suite',
                     license='Apache2.0',
                     packages=setuptools.find_packages(),
                     include_package_data=True,
                     tests_require=['pytest'],
                     install_requires=install_requires,
                     extras_require={'dev': DEV_PACKAGES},
                     scripts=scripts,
                     cmdclass={
                         'test': PyTest,
                         'install_deps': ActsInstallDependencies,
                         'uninstall': ActsUninstall
                     },
                     url="http://www.android.com/")

    if {'-u', '--uninstall', 'uninstall'}.intersection(sys.argv):
        installed_scripts = [
            '/usr/local/bin/act.py', '/usr/local/bin/monsoon.py'
        ]
        for act_file in installed_scripts:
            if os.path.islink(act_file):
                os.unlink(act_file)
            elif os.path.exists(act_file):
                os.remove(act_file)


if __name__ == '__main__':
    main()
