# CONFIDENTIAL. (C) 2022 Cadence Design Systems, Inc. (Cadence)
# All rights reserved.
# ALL SOFTWARE BELOW IS PROPRIETARY AND CONFIDENTIAL TO CADENCE
# AND IS SUBJECT TO THE FULL PROTECTION OF COPYRIGHT AND TRADE SECRET LAW.
# Copying or modifying this software is strictly prohibited and illegal.
# Using this software without a valid license from Cadence is strictly
# prohibited and illegal.  De-obfuscating, de-minimizing, or any other
# attempt to reverse engineer or discover the workings of this software,
# is strictly prohibited. Even if software is exposed or visible, it is
# still proprietary and confidential and the above prohibitions apply.
# This software is NOT "Sample Code". For purposes of customization or
# interoperation with other software you must use Sample Code
# specifically labeled as such.
# Please contact Cadence at eyesopen.com/legal if you have any questions
# about this warning.
import os
import sys
import platform
import subprocess

"""
OpenEye's current definition of 'architecture strings'.
"""


def _get_windows_platform():
    bits, name = platform.architecture()
    return ("win" + bits[:2],)


def _prepend_ucs(newname):
    if sys.version_info[:2] == (2, 7) and "ucs" not in newname:
        if sys.maxunicode == 65535:
            newname = "ucs2-" + newname
        else:
            newname = "ucs4-" + newname
    return newname


def _get_bits():
    nbits = platform.architecture()[0]
    machine = platform.machine()
    pyarch = {"64bit": "x64",
              "32bit": "x86"}[nbits]
    if machine == "aarch64":
        pyarch = "aarch64"
    return pyarch


def _get_mac_bits():
    return "universal"


def _get_mac_platform():
    return "osx", _get_mac_bits()


def _get_mac_platform_old():
    release, versioninfo, machine = platform.mac_ver()
    version = ".".join(release.split(".")[:2])
    if not version.startswith("10"):
        version = ".".join(release.split(".")[:1])
    return "osx", version, _get_mac_bits()


def _get_linux_platform():

    # Check for RHEL6, that one uses old distribution,
    # all other linux builds use generic single-build

    #if os.path.exists("/etc/redhat-release"):
    #    with open("/etc/redhat-release") as f:
    #        line = f.readline()
    #        if "release 6" in line:
    #            return "redhat", "6", "x64"

    # generic linux
    return _prepend_ucs("linux"), _get_bits()


def _get_linux_platform_old():
    if not hasattr(platform, 'linux_distribution'):
        try:
            import distro
        except ImportError:
            raise Exception("Missing linux_distribution support!")
        distname, version, extra = distro.linux_distribution(full_distribution_name=False)
    elif sys.version_info[:2] > (2, 5):
        distname, version, extra = platform.linux_distribution(full_distribution_name=False)
    else:
        distname, version, extra = platform.dist()

    distname = distname.lower()
    if "centos" in distname:
        distname = "redhat"

    if "amzn" in distname:
        distname = "amazon"
        version = "1"
        if distname == "amzn2":
            version = "2"

    if distname in ["redhat", "suse"]:
        version = version.split(".")[0]

    if "debian" in distname or "ubuntu" in distname:
        distname = "ubuntu"
        if "squeeze" in version:
            version = "10.04"

        # ubuntu12-64 alternate
        # ['ubuntu', '12.04', 'x64'] != ('ubuntu', 'wheezy/sid', 'x64')
        elif "wheezy" in version:
            version = "12.04"
        elif "trusty" in version:   # ubuntu14 beta
            version = "14.04"
        elif "jessie" in version:   # ubuntu14.04.2
            version = "14.04"
        elif "stretch" in version:  # ubuntu16.04.1
            version = "16.04"
        elif "buster" in version:   # ubuntu18.04
            version = "18.04"
        elif "bullseye" in version: # ubuntu20.04
            version = "20.04"
        elif "bookworm" in version: # ubuntu22.04
            version = "22.04"

    if not distname:
        # generic linux
        distname = platform.platform()
        if "amzn2" in distname:
            distname = "amazon"
            version = "2"
        else:
            distname = _prepend_ucs("linux")
            return distname, _get_bits()

    if (distname == "redhat" and version in ["5", "6"]):
        # only Anaconda python2.7 requires this special compilation status
        if (sys.version_info[:2] == (2, 7) and sys.maxunicode != 65535):
            distname = "anaconda-" + distname

    return distname, version, _get_bits()


def openeye_platform_old():
    if sys.platform.startswith("win"):
        return _get_windows_platform()

    if sys.platform.startswith("darwin"):
        return _get_mac_platform_old()

    if sys.platform.startswith("linux"):
        return _get_linux_platform_old()

    raise ValueError("Unrecognized platform '%s'" % sys.platform)


def openeye_platform():
    """
    Return a tuple corresponding to the (distname, version, bitness)
    of the machine being run on.

    Windows returns a single element tuple, either ('win32',) or
    ('win64',) for 32 or 64 bit respectively.

    If 'OE_PIP_ARCH' environment variable is set, return the first
    architecture specified in that string.
    """
    if "OE_PIP_ARCH" in os.environ:
        # Unlike OE_ARCH for app installs, Python only can act upon the
        # first entry in OE_PIP_ARCH. There is no way to iterate over a
        # list since the python requirements mechanism used to force the
        # download of the actual package from the metapackage isn't
        # recoverable if the first one fails.
        newname = os.environ["OE_PIP_ARCH"].split(":")[0]
        # force to use old naming
        if "old" in newname:
            return openeye_platform_old()
        # special for single builds
        if "linux" in newname:
            newname = _prepend_ucs(newname)
        # Apps use "redhat-RHEL6-...", python uses "redhat-6-..."
        # Remap to try to minimize confusion; no-op otherwise
        newname = newname.replace("redhat-RHEL", "redhat-", 1)
        return newname.split("-")

    if sys.platform.startswith("win"):
        return _get_windows_platform()

    if sys.platform.startswith("darwin"):
        return _get_mac_platform()

    if sys.platform.startswith("linux"):
        return _get_linux_platform()

    raise ValueError("Unrecognized platform '%s'" % sys.platform)


def openeye_python_version():
    """
    Return a string representation of the python version, e.g.,
    'python2.7'.

    For Python 3+, don't include the minor revision on non-Windows, just return
    'python3'.
    """
    verinfo = sys.version_info
    version = "python%i" % verinfo[0]
    if verinfo[0] <= 2 or sys.platform.startswith("win"):
        version += ".%i" % verinfo[1]
    return version


def openeye_python_compilers():
    """
    Return a list of strings for compatible compilers for this python
    interpretter. All platforms will return a single compiler.
    """
    # Is the user trying to use a non-supported system?
    if "OE_PYTHON_COMPILER" in os.environ:
        return [os.environ["OE_PYTHON_COMPILER"]]

    # Get the compiler used to compile python
    comp = platform.python_compiler()

    compilers = []

    try:
        if len(comp) > 1:
            cxx, ver = comp.split()[:2]

            cxx = cxx.lower()
            if cxx == "gcc":
                cxx = "g++"

            ver = ver.split('.') + ['0']

            # single builds
            if "linux" in '-'.join(openeye_platform()) and cxx == "g++":
                ver = '.'.join([ver[0], "x"])
            else:
                ver = '.'.join(ver[:2])

            compilers.append(cxx + ver)
    except ValueError:
        pass

    if not compilers:
        compilers.append(comp)

    return compilers
