#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (C) 2019 Apple Inc.  All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

from __future__ import print_function

import argparse
import os
import subprocess
import sys
import traceback

# Gather information about our debugging environment right now. Do this before
# executing any "main" code so that our debugging preferences are in place by
# the time we get there and we can debug from main() on down as opposed to
# parse_args() on down.

SHOW_DEBUG_LOGGING = "-d" in sys.argv or "--debug" in sys.argv

if SHOW_DEBUG_LOGGING:

    DEBUG_LOGGING_FILE = None
    for index, arg in enumerate(sys.argv):
        if arg == "--debug-file":
            if index + 1 < len(sys.argv):
                DEBUG_LOGGING_FILE = sys.argv[index + 1]

    # Bottleneck function for printing debugging lines to either the console or
    # the screen, as appropriate.

    if DEBUG_LOGGING_FILE:

        def debug_log(msg):
            with open(DEBUG_LOGGING_FILE, "a") as f:
                print(msg, file=f)
    else:

        def debug_log(msg):
            print(msg)

    # Context Manager class for logging information about function entry/exit.
    # On entry, the function name is logged along with its parameters. On exit,
    # the function name is logged with its result. If an exception occurs, the
    # function name is logged with the exception. In all cases, the logging is
    # indented according to the level of the function in the backtrace.
    #
    # Versions of these classes exist for instance methods, class methods, and
    # global functions so that instance and class information can be extracted
    # and displayed.

    class LogEntryHelper(object):
        __slots__ = ["indent", "class_name", "function_name", "type"]

        def __init__(self, func, type):
            tb = traceback.extract_stack()
            self.indent = " " * 2 * (len(tb) - 3)
            self.class_name = None
            self.function_name = func.__name__
            self.type = type

        def log_entry(self, args, kwargs):
            if self.type == "instance":
                self.class_name = args[0].__class__.__name__ + "."
                args = args[1:]
            elif self.type == "class":
                self.class_name = args[0].__name__ + "."
                args = args[1:]
            else:
                self.class_name = ""

            self._print("args={}, kwargs={}".format(args, kwargs))

        def log_result(self, result):
            if hasattr(result, '__iter__') and not isinstance(result, str):
                for line in result:
                    self._print("result={}".format(line))
            else:
                self._print("result={}".format(result))

        def log_exception(self, exc):
            self._print("exception={}".format(exc))

        def _print(self, msg):
            debug_log("{}{}{}: {}".format(self.indent, self.class_name, self.function_name, msg))

    def LogEntryExit(func):
        def _show_debug_logging(*args, **kwargs):
            helper = LogEntryHelper(func, "instance")
            helper.log_entry(args, kwargs)
            try:
                result = func(*args, **kwargs)
                helper.log_result(result)
                return result
            except BaseException as e:
                helper.log_exception(e)
                raise
        return _show_debug_logging

    def LogEntryExitClass(func):
        def _show_debug_logging(*args, **kwargs):
            helper = LogEntryHelper(func, "class")
            helper.log_entry(args, kwargs)
            try:
                result = func(*args, **kwargs)
                helper.log_result(result)
                return result
            except BaseException as e:
                helper.log_exception(e)
                raise
        return _show_debug_logging

    def LogEntryExitGlobal(func):
        def _show_debug_logging(*args, **kwargs):
            helper = LogEntryHelper(func, None)
            helper.log_entry(args, kwargs)
            try:
                result = func(*args, **kwargs)
                helper.log_result(result)
                return result
            except BaseException as e:
                helper.log_exception(e)
                raise
        return _show_debug_logging

else:

    def debug_log(msg):
        pass

    def LogEntryExit(func):
        return func

    def LogEntryExitClass(func):
        return func

    def LogEntryExitGlobal(func):
        return func


# Utility function for operating similar to subprocess.run() in Python 3. One
# difference is that the result is a 2-tuple with stdout and stderr, rather
# than a 3-tuple that includes returncode. For our purposes, if returncode is
# non-zero, we raise an exception.

@LogEntryExitGlobal
def subprocess_run(args, **kwargs):
    kwargs["stdout"] = subprocess.PIPE
    kwargs["stderr"] = subprocess.PIPE
    input = None
    if "input" in kwargs:
        input = kwargs["input"]
        del kwargs["input"]
        kwargs["stdin"] = subprocess.PIPE
    process = subprocess.Popen(args, **kwargs)
    (stdout, stderr) = process.communicate(input=input)
    stdout = stdout.decode() if isinstance(stdout, bytes) else stdout
    stderr = stderr.decode() if isinstance(stderr, bytes) else stderr
    if process.returncode:
        raise CalledProcessError(process.returncode, args[0], stdout, stderr)
    return (stdout, stderr)


# Utility function to allow us to verify that we're running under Xcode or not.
# For example, if we are not, then we need to make sure that we don't try to
# access Xcode-specific environment variables.
#
# Note: This function use to check XCODE_INSTALL_PATH. Because if Xcode is
# running, it must have been installed. That's the theory, anyway. In
# actuality, it seems possible to install Xcode without the result having
# XCODE_INSTALL_PATH defined. So now we check XCODE_PRODUCT_BUILD_VERSION.

@LogEntryExitGlobal
def is_running_under_xcode():
    return os.environ.get("XCODE_PRODUCT_BUILD_VERSION")


# An argparse.Action subclass that validates the user-provided value against a
# list of valid values. Aliasing is supported; that is, the user can provide a
# value that can get mapped to a corresponding canonical value, and that
# resulting value is compared to the list of valid values.
#
# On error, calls parser.error().

class CheckValidItemAction(argparse.Action):
    @LogEntryExit
    def __init__(self, *args, **kwargs):
        self.item_type = kwargs.get("item_type", None)
        self.valid_items = kwargs.get("valid_items", None)
        self.aliases = kwargs.get("aliases", None)

        self.lowered_valid_items = [item.lower() for item in self.valid_items]

        kwargs.pop("item_type", None)
        kwargs.pop("valid_items", None)
        kwargs.pop("aliases", None)

        super(CheckValidItemAction, self).__init__(*args, **kwargs)

    @LogEntryExit
    def __call__(self, parser, namespace, values, option_string=None):
        try:
            validated = self.validate_item(values)
        except:
            parser.error("The {} \"{}\" is not supported.".format(self.item_type, values))
        items = getattr(namespace, self.dest, None)
        items = items[:] if items else []
        items.append(validated)
        setattr(namespace, self.dest, items)

    @LogEntryExit
    def validate_item(self, item):
        item = item.lower()
        try:
            validated_index = self.lowered_valid_items.index(item)
        except:
            if not self.aliases:
                raise
            item = self.aliases.get(item, None)
            validated_index = self.lowered_valid_items.index(item)
        return self.valid_items[validated_index]


# An argparse.Action subclass that validates the user-provided script command
# (generate, check, etc.)
#
# On error, calls parser.error().

class CheckCommandAction(argparse.Action):
    @LogEntryExit
    def __init__(self, *args, **kwargs):
        self.valid_commands = kwargs.get("valid_commands", None)
        kwargs.pop("valid_commands", None)
        super(CheckCommandAction, self).__init__(*args, **kwargs)

    @LogEntryExit
    def __call__(self, parser, namespace, value, option_string=None):
        if not value in self.valid_commands:
            parser.error('"{}" is not a valid command'.format(value))
        setattr(namespace, self.dest, value)


# Some Exceptions

class InvalidCommandError(Exception):
    pass


class InvalidArgumentError(Exception):
    pass


class InvalidConfigurationError(Exception):
    pass


# subprocess.CalledProcessError has problems with being pickled, which is
# something that we do to it. In particular, when unpickled, it throws an
# exception, and so CalledProcessError get's turned into an exception saying
# "__init__() takes at least 3 arguments (1 given)". Address this by creating
# our own CalledProcessError that's a little more generic.

class CalledProcessError(Exception):
    def __str__(self):
        returncode = self.args[0] if len(self.args) > 0 else None
        command = self.args[1] if len(self.args) > 1 else None
        stdout = self.args[2] if len(self.args) > 2 else None
        stderr = self.args[3] if len(self.args) > 3 else None

        if stderr:
            return "Command '{}' returned non-zero exit status {}: {}".format(command, returncode, stderr)
        elif stdout:
            return "Command '{}' returned non-zero exit status {}: {}".format(command, returncode, stdout)
        else:
            return "Command '{}' returned non-zero exit status {}".format(command, returncode)
