#!/usr/bin/env python
# this script sets up the testing packages to allow the tests

#  Licensed to the Apache Software Foundation (ASF) under one
#  or more contributor license agreements.  See the NOTICE file
#  distributed with this work for additional information
#  regarding copyright ownership.  The ASF licenses this file
#  to you 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 __future__ import absolute_import, division, print_function

import argparse
import os
import subprocess
import sys

try:
    from distro import linux_distribution
except ImportError:
    from platform import linux_distribution


pip_packages = [
    "autest==1.10.0",
    "hyper",
    "requests",
    "dnslib",
    "httpbin",
    "gunicorn",
    "traffic-replay"  # this should install TRLib, MicroServer, MicroDNS, Traffic-Replay
]


distro_packages = {
    "RHEL": [
        "install epel-release",
        "install python36",
        "install rh-python36-python-virtualenv"
    ],
    "Fedora": [
        "install python3",
        "install python3-virtualenv",
        "install python-virtualenv",
    ],
    "Ubuntu": [
        "install python3",
        "install python3-virtualenv",
        "install virtualenv",
        "install python3-dev"
    ],
    "CentOS": [
        "install epel-release",
        "install rh-python36-python-virtualenv"
    ],
    "CentOS-8": [
        "install epel-release",
        "install python3-virtualenv"
    ],
    "Rocky": [
        "install epel-release",
        "install python3-virtualenv"
    ]
}


def command_output(cmd_str):
    print(cmd_str)
    proc = subprocess.Popen(
        cmd_str,
        shell=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,
        universal_newlines=True)

    # while command runs get output
    while proc.poll() == None:
        tmp = proc.stdout.readline()
        sys.stdout.write(tmp)

    for last_output in proc.stdout.readlines():
        sys.stdout.write(last_output)

    return proc.returncode


def get_distro():
    return linux_distribution()


def distro_version():
    return int(get_distro()[1].split(".")[0])


def isFedora():
    return get_distro()[0].startswith("Fedora")


def isCentOS():
    return get_distro()[0].startswith("CentOS")


def distro():
    if isFedora():
        return "Fedora"
    if isCentOS():
        return "CentOS"
    if get_distro()[0].startswith("Red Hat"):
        return "RHEL"
    if get_distro()[0].startswith("Ubuntu"):
        return "Ubuntu"


def isRedHatBased():
    return get_distro()[0].startswith("Red Hat") or get_distro()[0].startswith(
        "Fedora") or get_distro()[0].startswith("CentOS")


def isInstalled(prog):
    out = subprocess.Popen(
        ["which", prog], stdout=subprocess.PIPE).communicate()
    if out[0] != '':
        return True
    return False


def installManagerName():
    if isRedHatBased() and distro_version() >= 22:
        ret = "sudo dnf -y"  # Fedora 22 or newer
    elif isRedHatBased():
        ret = "sudo yum -y"  # Red Hat distro
    else:
        ret = "sudo apt-get -y"  # Ubuntu/Debian

    return ret


def installToolName():
    if isRedHatBased():
        ret = "rpm -ihv"  # Red Hat Based
    else:
        ret = "dpkg -iv"  # Ubuntu/Debian

    return ret


def run_cmds(cmds):
    for cmd in cmds:
        # print (cmd.split[" "])
        # subprocess.call(cmd.split[" "])
        if command_output(cmd):
            print("'{0}'' - Failed".format(cmd))


def gen_package_cmds(packages):

    # main install tool/manager (yum, dnf, apt-get, etc)
    mtool = installManagerName()
    # core install tool (rpm, dpkg, etc)
    itool = installToolName()
    ret = []

    for p in packages:
        if p.startswith("wget"):
            pth = p[5:]
            pack = os.path.split(pth)[1]
            cmd = ["wget {0}".format(pth), "{0} ./{1}".format(itool, pack)]
        else:
            cmd = ["{0} {1}".format(mtool, p)]
        ret.extend(cmd)
    return ret


extra = ''
if distro() == 'RHEL' or (distro() == 'CentOS' and distro_version() < 8):
    extra = ". /opt/rh/rh-python36/enable ;"


def venv_cmds(path):
    '''
    Create virtual environment and add it
    to the path being used for the script
    '''

    return [
        # first command only needed for rhel and centos systems at this time
        extra + " virtualenv --python=python3 {0}".format(path),
        extra + " {0}/bin/pip install pip setuptools --upgrade".format(path)
    ]


def main():
    " main script logic"
    parser = argparse.ArgumentParser()

    parser.add_argument(
        "--use-pip", nargs='?', default="pip", help="Which pip to use")

    parser.add_argument(
        "venv_path",
        nargs='?',
        default="env-test",
        help="The directory to us to for the virtualenv")

    parser.add_argument(
        "--disable-virtualenv",
        default=False,
        action='store_true',
        help="Do not create virtual environment to install packages under")

    parser.add_argument(
        '-V', '--version', action='version', version='%(prog)s 1.0.0')

    args = parser.parse_args()
    # print(args)
    # print(get_distro())

    # do we know of packages to install for the given platform
    dist = distro()
    cmds = []

    if dist:
        if distro() == 'CentOS' and distro_version() > 7:
            # if centos 8 we must set crypto to legacy to allow tlsv1.0 tests
            cmds += ["sudo update-crypto-policies --set LEGACY"]
            cmds += gen_package_cmds(distro_packages['CentOS-8'])
        else:
            cmds += gen_package_cmds(distro_packages[dist])

    # test to see if we should use a certain version of pip
    path_to_pip = None
    if args.use_pip != "pip":
        path_to_pip = args.use_pip

    # install on the system, or use virtualenv for pip based stuff
    if not args.disable_virtualenv:
        # Create virtual env
        cmds += venv_cmds(args.venv_path)
        if path_to_pip is None:
            path_to_pip = os.path.join(args.venv_path, "bin", args.use_pip)

    cmds += [extra + "{0} install {1}".format(path_to_pip, " ".join(pip_packages))]

    run_cmds(cmds)


if __name__ == '__main__':
    main()
