# Copyright 2016 gRPC authors.
#
# 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 os.path
import shutil
import sys
import tempfile

from setuptools import errors

import commands

C_PYTHON_DEV = """
#include <Python.h>
int main(int argc, char **argv) { return 0; }
"""
C_PYTHON_DEV_ERROR_MESSAGE = """
Could not find <Python.h>. This could mean the following:
  * You're on Ubuntu and haven't run `apt-get install <PY_REPR>-dev`.
  * You're on RHEL/Fedora and haven't run `yum install <PY_REPR>-devel` or
    `dnf install <PY_REPR>-devel` (make sure you also have redhat-rpm-config
    installed)
  * You're on Mac OS X and the usual Python framework was somehow corrupted
    (check your environment variables or try re-installing?)
  * You're on Windows and your Python installation was somehow corrupted
    (check your environment variables or try re-installing?)
"""
if sys.version_info[0] == 2:
    PYTHON_REPRESENTATION = "python"
elif sys.version_info[0] == 3:
    PYTHON_REPRESENTATION = "python3"
else:
    raise NotImplementedError("Unsupported Python version: %s" % sys.version)

C_CHECKS = {
    C_PYTHON_DEV: C_PYTHON_DEV_ERROR_MESSAGE.replace(
        "<PY_REPR>", PYTHON_REPRESENTATION
    ),
}


def _compile(compiler, source_string):
    tempdir = tempfile.mkdtemp()
    cpath = os.path.join(tempdir, "a.c")
    with open(cpath, "w") as cfile:
        cfile.write(source_string)
    try:
        compiler.compile([cpath])
    except errors.CompileError as error:
        return error
    finally:
        shutil.rmtree(tempdir)


def _expect_compile(compiler, source_string, error_message):
    if _compile(compiler, source_string) is not None:
        sys.stderr.write(error_message)
        raise commands.CommandError(
            "Diagnostics found a compilation environment issue:\n{}".format(
                error_message
            )
        )


def diagnose_compile_error(build_ext, error):
    """Attempt to diagnose an error during compilation."""
    for c_check, message in C_CHECKS.items():
        _expect_compile(build_ext.compiler, c_check, message)
    python_sources = [
        source
        for source in build_ext.get_source_files()
        if source.startswith("./src/python") and source.endswith("c")
    ]
    for source in python_sources:
        if not os.path.isfile(source):
            raise commands.CommandError(
                (
                    "Diagnostics found a missing Python extension source"
                    " file:\n{}\n\nThis is usually because the Cython sources"
                    " haven't been transpiled into C yet and you're building"
                    " from source.\nTry setting the environment variable"
                    " `GRPC_PYTHON_BUILD_WITH_CYTHON=1` when invoking"
                    " `setup.py` or when using `pip`, e.g.:\n\npip install"
                    " -rrequirements.txt\nGRPC_PYTHON_BUILD_WITH_CYTHON=1 pip"
                    " install ."
                ).format(source)
            )


def diagnose_attribute_error(build_ext, error):
    if any("_needs_stub" in arg for arg in error.args):
        raise commands.CommandError(
            "We expect a missing `_needs_stub` attribute from older versions of"
            " setuptools. Consider upgrading setuptools."
        )


_ERROR_DIAGNOSES = {
    errors.CompileError: diagnose_compile_error,
    AttributeError: diagnose_attribute_error,
}


def diagnose_build_ext_error(build_ext, error, formatted):
    diagnostic = _ERROR_DIAGNOSES.get(type(error))
    if diagnostic is None:
        raise commands.CommandError(
            "\n\nWe could not diagnose your build failure with type {}. If you are unable to"
            " proceed, please file an issue at http://www.github.com/grpc/grpc"
            " with `[Python install]` in the title; please attach the whole log"
            " (including everything that may have appeared above the Python"
            " backtrace).\n\n{}".format(type(error), formatted)
        )
    else:
        diagnostic(build_ext, error)
