#!/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.

# Application represents the main operation of the script. It's a singleton,
# created by main() and then invoked to run everything. This class parses the
# command-line options, validates them, creates and invokes BaseGenerators,
# reports the results, and handles the catching and reporting of any
# exceptions/errors.

from __future__ import print_function

import argparse
import itertools
import os
import sys
import textwrap
import traceback

from functools import reduce

import webkitpy.generate_xcfilelists_lib.generators as Generators
import webkitpy.generate_xcfilelists_lib.util as util


EX_GENERAL_ERROR = 1  # General error
EX_ACTION_REQUIRED = 2  # Returned when script determines that the generated .xcfilelist files have changed.


class Application(object):

    __slots__ = (
        "command_file",
        "parser", "cmd_line_args",
        "dispatch", "project_specific_generators",
        "supported_project_tags", "supported_platforms", "supported_configurations")

    # Aliases for platforms. These are handy when using the script from the
    # command line and you don't remember if it's "ios" or "iphoneos, or "tvos"
    # or "appletvos". This list of aliases will let you use any of those.

    platform_aliases = {
        "ios":          "iphoneos",
        "iphone":       "iphoneos",
        "simulator":    "iphonesimulator",
        "sim":          "iphonesimulator",
        "mac":          "macosx",
        "macos":        "macosx",
        "osx":          "macosx",
        "tvos":         "appletvos",
        "tv":           "appletvos",
        "tvsimulator":  "appletvsimulator",
        "watch":        "watchos",
    }

    @util.LogEntryExit
    def __init__(self, command_file):
        self.command_file = os.path.realpath(command_file)
        self.parser = None
        self.cmd_line_args = None

        self.dispatch = {
            "generate":       self._cmd_set_environment_and_generate,
            "generate-xcode": self._cmd_generate_within_xcode,
            "check":          self._cmd_set_environment_and_check,
            "check-xcode":    self._cmd_check_within_xcode,
            "generate-inner": self._cmd_generate_within_xcode_and_return_results_to_caller,
            "help":           self._cmd_help,
        }

        self.project_specific_generators = {
            "JavaScriptCore":   Generators.JavaScriptCoreGenerator,
            "WebCore":          Generators.WebCoreGenerator,
            "WebKit":           Generators.WebKitGenerator,
            "WebKitLegacy":     Generators.WebKitLegacyGenerator,
            "DumpRenderTree":   Generators.DumpRenderTreeGenerator,
            "WebKitTestRunner": Generators.WebKitTestRunnerGenerator,
            "TestWebKitAPI":    Generators.TestWebKitAPIGenerator,
        }

        self.supported_project_tags = None
        self.supported_platforms = None
        self.supported_configurations = None

    @util.LogEntryExit
    def run(self):
        try:
            self._initialize()

            self.parser = self._create_parser()
            self.cmd_line_args = args = self.parser.parse_args()

            if args.help:
                return self._cmd_help(os.EX_OK)

            self._validate_args(args)

            try:
                func = self.dispatch[args.command]
            except KeyError:
                raise util.InvalidCommandError(args.command)

            return func()

        except util.InvalidArgumentError as e:
            print("### Invalid argument: {}".format(e))
            return self._cmd_help(os.EX_USAGE)

        except util.InvalidCommandError as e:
            if e.args:
                print("### Invalid command: {}".format(e))
            else:
                print("### Missing command")
            return self._cmd_help(os.EX_USAGE)

        except SystemExit:
            raise

        except BaseException:
            traceback.print_exc()
            return os.EX_SOFTWARE

    # Perform some post __init__ initialization. This is performed after
    # __init__ so that we can respond to any information provided in any
    # sub-class's __init__.

    @util.LogEntryExit
    def _initialize(self):
        def collect_attributes(key):
            configurations = set()
            for project_tag in self.project_specific_generators:
                configurations |= set(key(self.project_specific_generators[project_tag]))
            return configurations

        self.supported_project_tags = sorted(list(self.project_specific_generators.keys()))
        self.supported_platforms = sorted(list(collect_attributes(lambda gen_cls: gen_cls.VALID_PLATFORMS)))
        self.supported_configurations = sorted(list(collect_attributes(lambda gen_cls: gen_cls.VALID_CONFIGURATIONS)))

    @util.LogEntryExit
    def _create_parser(self):
        valid_commands = ("generate", "generate-xcode", "check", "check-xcode", "generate-inner", "help")
        valid_commands_prompt = "(" + " | ".join(valid_commands) + ")"

        parser = argparse.ArgumentParser(add_help=False,
                formatter_class=argparse.RawDescriptionHelpFormatter,
                description="""\
Generate or check .xcfilelist files. One of the following commands must be
specified on the command-line:

  generate              Generate a complete and up-to-date set of .xcfilelist
                        files and copy them to their appropriate places in the
                        project directories.
  generate-xcode        Similar to generate, but to be called from within Xcode.
  check                 Generate a complete and up-to-date set of .xcfilelist
                        files and compare them to their counterparts in the
                        project directories.
  check-xcode           Similar to check, but to be called from within Xcode.
  generate-inner        [Used by script internals] Generate an .xcfilelist file
                        for a particular combination of project, platform, and
                        configuration. This operation is performed in the
                        context of an Xcode build in order to inherit the same
                        environment as that build. Once generated, the results
                        are returned to the calling instance of this script.
  help                  Print this text and exit.""")

        parser.add_argument("command", action=util.CheckCommandAction,
                valid_commands=valid_commands, metavar=valid_commands_prompt,
                help="""\
                        The operation to perform.""")

        parser.add_argument("--project", action=util.CheckValidItemAction,
                item_type="project",
                valid_items=self.supported_project_tags,
                dest="project_tags", metavar="<PROJECT>", help="""\
                        Specify which project or projects for which to generate
                        .xcfilelist files or to check. Possible values are
                        ({}). Can be specified more than once. Default is to
                        iterate over all projects.""".format(
                            ", ".join(self.supported_project_tags)))
        parser.add_argument("--platform", action=util.CheckValidItemAction,
                item_type="platform",
                valid_items=self.supported_platforms,
                aliases=self.platform_aliases,
                dest="platforms", metavar="<PLATFORM>", help="""\
                        Specify which platform or platforms for which to
                        generate .xcfilelist files or to check. Possible values
                        are ({}, plus common aliases). Can be specified more
                        than once. Default is to iterate over all platforms,
                        filtered to those platforms that a particular project
                        supports (e.g., you can't specify 'iphoneos' for
                        WebKitTestRunner).""".format(
                            ", ".join(self.supported_platforms)))
        parser.add_argument("--configuration", action=util.CheckValidItemAction,
                item_type="configuration",
                valid_items=self.supported_configurations,
                dest="configurations", metavar="<CONFIGURATION>", help="""\
                        Specify which configuration or configurations for which
                        to generate .xcfilelist files or to check. Possible
                        values are ({}). Can be specified more than once.
                        Default is to iterate over all
                        configurations.""".format(
                            ", ".join(self.supported_configurations)))
        parser.add_argument("--xcode", metavar="<WORKSPACE>", help="""\
                        If the existing build output was created by building
                        with Xcode, specify the path to the workspace that was
                        used.""")
        parser.add_argument("-d", "--debug", action="store_true", help="""\
                        Provide verbose output.""")
        parser.add_argument("--debug-file", help="""\
                        [Used by script internals] Name of the file to which to
                        write debug information. Used when this script
                        sub-launches itself and needs to collect the debug
                        information from the sub-launched instance. Not
                        normally used when this script is invoked from the
                        command-line or Xcode.""")
        parser.add_argument("--pickle-file", help="""\
                        [Used by script internals] Name of the file used to
                        store results to be transported out from the Xcode
                        execution environment out to an outer layer. This
                        parameter is only used with the 'generate-core'
                        command.""")
        parser.add_argument("-q", "--quiet", action="store_true", help="""\
                        Don't print any standard output.""")
        parser.add_argument("-h", "--help", action="store_true", help="""\
                        Print this text and exit.""")

        setattr(parser, "application", self)
        return parser

    @util.LogEntryExit
    def _validate_args(self, args):
        if not self.cmd_line_args.project_tags:
            self.cmd_line_args.project_tags = self.supported_project_tags
        if not self.cmd_line_args.platforms:
            self.cmd_line_args.platforms = self.supported_platforms
        if not self.cmd_line_args.configurations:
            self.cmd_line_args.configurations = self.supported_configurations

        if util.is_running_under_xcode():
            assert len(self.cmd_line_args.project_tags) == 1
            assert len(self.cmd_line_args.platforms) == 1
            assert len(self.cmd_line_args.configurations) == 1

    @util.LogEntryExit
    def _cmd_set_environment_and_generate(self):
        generators = self._do_set_environment_and_generate()
        generators = self._do_merge(generators)
        return self._report_results(generators)

    @util.LogEntryExit
    def _cmd_generate_within_xcode(self):
        generators = self._do_generate()
        generators = self._do_merge(generators)
        return self._report_results(generators)

    @util.LogEntryExit
    def _cmd_set_environment_and_check(self):
        generators = self._do_set_environment_and_generate()
        return self._report_results(generators)

    @util.LogEntryExit
    def _cmd_check_within_xcode(self):
        generators = self._do_generate()
        return self._report_results(generators)

    @util.LogEntryExit
    def _cmd_generate_within_xcode_and_return_results_to_caller(self):
        generators = self._do_generate()
        with open(self.cmd_line_args.pickle_file, "wb") as f:
            for generator in generators:
                generator.pickle_to_file(f)
        return os.EX_OK

    @util.LogEntryExit
    def _cmd_help(self, status=os.EX_OK):
        self.parser.print_help()
        return status

    @util.LogEntryExit
    def _do_set_environment_and_generate(self):
        def core_operation(generator, generators):
            new_generators = generator.set_environment_and_generate()
            generators.extend(new_generators)
            return generators
        return self._do_generate_common(core_operation)

    @util.LogEntryExit
    def _do_generate(self):
        def core_operation(generator, generators):
            generator.generate()
            generators.append(generator)
            return generators
        return self._do_generate_common(core_operation)

    @util.LogEntryExit
    def _do_generate_common(self, core_operation):
        generators = []

        for triple in itertools.product(
                self.cmd_line_args.project_tags,
                self.cmd_line_args.platforms,
                self.cmd_line_args.configurations):
            generator = self.project_specific_generators[triple[0]](self, *triple)
            if not generator.is_valid():
                continue
            self._log_progress("Generating .xcfilelists for {}/{}/{}".format(*triple))
            try:
                generators = core_operation(generator, generators)
            except BaseException:
                # TODO: Turn the traceback into a string, and then allow
                # this field to be pickled and printed by the calling
                # context. Right now, pickling raises an exception if it
                # encounters a Traceback object. See BaseGenerator.pickle_to_file.
                (generator.ex_type, generator.ex_value, generator.ex_traceback) = sys.exc_info()
            if generator.has_error():
                sys.exit(self._report_results([generator]))

        return generators

    @util.LogEntryExit
    def _do_merge(self, generators):
        if self._any_have_errors(generators):
            return generators

        for generator in generators:
            if generator.has_action():
                self._log_progress("Merging .xcfilelists for {}/{}/{}".format(*generator.triple))
                generator.merge()

        return generators

    @util.LogEntryExit
    def _report_results(self, generators):
        generators_with_errors = [generator for generator in generators if generator.has_error()]
        if generators_with_errors:
            for generator in generators_with_errors:
                generator.report_error()
            return EX_GENERAL_ERROR

        generators_with_actions = [generator for generator in generators if generator.has_action()]
        if generators_with_actions:
            if self.cmd_line_args.command == "generate" or self.cmd_line_args.command == "generate-xcode":
                self._report_merge_results(generators_with_actions)
            else:
                self._report_remediation_steps(generators_with_actions)
            return EX_ACTION_REQUIRED

        return os.EX_OK

    @util.LogEntryExit
    def _report_merge_results(self, generators):
        message = textwrap.wrap(
                "\".xcfilelist\" files tell the build system what files are " +
                "consumed and produced by the \"Run Script\" build phases in " +
                "Xcode. At least one of these .xcfilelist files was out of date " +
                "and has been updated. You now need to restart your build.", 90)

        self._log_results("")
        for line in message:
            self._log_results(line)

    @util.LogEntryExit
    def _report_remediation_steps(self, generators):
        message = textwrap.wrap("One or more \".xcfilelist\" files are out of date. Regenerate them by running the following commands:", 90)
        message.append("")

        def add_to_message(generator, message):
            if generator.has_action():
                message.append("    `Tools/Scripts/generate-xcfilelists generate --project {} --platform {} --configuration {}{}`\n".format(
                        generator.project_tag, generator.platform, generator.configuration,
                        " --xcode {}".format(self.cmd_line_args.xcode) if self.cmd_line_args.xcode else ""))
            return message

        for generator in generators:
            message = add_to_message(generator, message)

        for line in message:
            self._log_results(line)

    @util.LogEntryExit
    def _any_have_errors(self, generators):
        return reduce(lambda acc, generator: acc or generator.has_error(), generators, None)

    @util.LogEntryExit
    def _any_have_actions(self, generators):
        return reduce(lambda acc, generator: acc or generator.has_action(), generators, None)

    @util.LogEntryExit
    def _log_progress(self, message):
        if not self.cmd_line_args.quiet:
            print("### {}".format(message))

    @util.LogEntryExit
    def _log_results(self, message):
        if not self.cmd_line_args.quiet:
            print("{}".format(message))

    # Return the path to the script to sublaunch.

    @util.LogEntryExit
    def get_generate_xcfilelists_script_path(self):
        return self.command_file

    # Return the parent of the WebKit check-out directory.

    @util.LogEntryExit
    def _get_root_parent_dir(self):
        return os.path.dirname(     # Remove "OpenSource"
                os.path.dirname(        # Remove "Tools"
                    os.path.dirname(        # Remove "Scripts"
                        os.path.dirname(        # Remove script name
                            self.get_generate_xcfilelists_script_path()))))

    # Return the path to the WebKit check-out directory.

    @util.LogEntryExit
    def get_opensource_dir(self):
        return os.path.join(self._get_root_parent_dir(), "OpenSource")

    # Return the path to the directory containing supporting build scripts.

    @util.LogEntryExit
    def get_build_scripts_dir(self):
        return os.path.join(self.get_opensource_dir(), "Source", "WTF", "Scripts")

    # Return the path to a supporting build script.

    @util.LogEntryExit
    def get_extract_dependencies_from_makefile_script(self):
        return os.path.join(self.get_opensource_dir(), "Tools", "Scripts", "extract-dependencies-from-makefile")

    # Return $(BUILT_PRODUCTS_DIR)
    # aka $(CONFIGURATION_BUILD_DIR)
    # aka $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)

    @util.LogEntryExit
    def get_xcode_built_products_dir(self):
        assert util.is_running_under_xcode()
        return self._getenv("BUILT_PRODUCTS_DIR")

    @util.LogEntryExit
    def get_xcode_project_temp_dir(self):
        assert util.is_running_under_xcode()
        return self._getenv("PROJECT_TEMP_DIR")

    # Return the named environment variable.
    @util.LogEntryExit
    def _getenv(self, variable_name):
        return os.environ.get(variable_name)
