#!/usr/bin/env python
#
# Copyright (c) 2015-2016 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. AND ITS CONTRIBUTORS ``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 ITS 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.

import logging
import re
import os

from builtins_templates import BuiltinsGeneratorTemplates as Templates

log = logging.getLogger('global')

_FRAMEWORK_CONFIG_MAP = {
    "JavaScriptCore": {
        "macro_prefix": "JSC",
        "namespace": "JSC",
    },
    "WebCore": {
        "macro_prefix": "WEBCORE",
        "namespace": "WebCore",
    },
}

functionHeadRegExp = re.compile(r"(?:@[\w|=\[\] \"\.]+\s*\n)*(?:async\s+)?function\s+\w+\s*\(.*?\)", re.MULTILINE | re.DOTALL)
functionGlobalPrivateRegExp = re.compile(r".*^@globalPrivate", re.MULTILINE | re.DOTALL)
functionIntrinsicRegExp = re.compile(r".*^@intrinsic=(\w+)", re.MULTILINE | re.DOTALL)
functionIsConstructorRegExp = re.compile(r".*^@constructor", re.MULTILINE | re.DOTALL)
functionIsGetterRegExp = re.compile(r".*^@getter", re.MULTILINE | re.DOTALL)
functionIsAsyncRegExp = re.compile(r"(async)?\s*function", re.MULTILINE | re.DOTALL)
functionNameRegExp = re.compile(r"function\s+(\w+)\s*\(", re.MULTILINE | re.DOTALL)
functionOverriddenNameRegExp = re.compile(r".*^@overriddenName=(\".+\")$", re.MULTILINE | re.DOTALL)
functionParameterFinder = re.compile(r"^(?:async\s+)?function\s+(?:\w+)\s*\(((?:\s*\w+)?\s*(?:\s*,\s*\w+)*)?\s*\)", re.MULTILINE | re.DOTALL)

multilineCommentRegExp = re.compile(r"\/\*.*?\*\/", re.MULTILINE | re.DOTALL)
singleLineCommentRegExp = re.compile(r"\/\/.*?\n", re.MULTILINE | re.DOTALL)
keyValueAnnotationCommentRegExp = re.compile(r"^\/\/ @(\w+)=([^=]+?)\n", re.MULTILINE | re.DOTALL)
flagAnnotationCommentRegExp = re.compile(r"^\/\/ @(\w+)[^=]*?\n", re.MULTILINE | re.DOTALL)
lineWithOnlySingleLineCommentRegExp = re.compile(r"^\s*\/\/\n", re.MULTILINE | re.DOTALL)
lineWithTrailingSingleLineCommentRegExp = re.compile(r"\s*\/\/\n", re.MULTILINE | re.DOTALL)
leadingWhitespaceRegExp = re.compile(r"^ +", re.MULTILINE | re.DOTALL)
multipleEmptyLinesRegExp = re.compile(r"\n{2,}", re.MULTILINE | re.DOTALL)

class ParseException(Exception):
    pass


class Framework:
    def __init__(self, name):
        self._settings = _FRAMEWORK_CONFIG_MAP[name]
        self.name = name

    def setting(self, key, default=''):
        return self._settings.get(key, default)

    @staticmethod
    def fromString(frameworkString):
        if frameworkString == "JavaScriptCore":
            return Frameworks.JavaScriptCore

        if frameworkString == "WebCore":
            return Frameworks.WebCore

        raise ParseException("Unknown framework: %s" % frameworkString)


class Frameworks:
    JavaScriptCore = Framework("JavaScriptCore")
    WebCore = Framework("WebCore")


class BuiltinObject:
    def __init__(self, object_name, annotations, functions):
        self.object_name = object_name
        self.annotations = annotations
        self.functions = functions
        self.collection = None  # Set by the owning BuiltinsCollection

        for function in self.functions:
            function.object = self


class BuiltinFunction:
    def __init__(self, function_name, function_source, parameters, is_async, is_constructor, is_global_private, intrinsic, overridden_name):
        self.function_name = function_name
        self.function_source = function_source
        self.parameters = parameters
        self.is_async = is_async
        self.is_constructor = is_constructor
        self.is_global_private = is_global_private
        self.intrinsic = intrinsic
        self.overridden_name = overridden_name
        self.object = None  # Set by the owning BuiltinObject

    @staticmethod
    def fromString(function_string):
        function_source = multilineCommentRegExp.sub("", function_string)

        intrinsic = "NoIntrinsic"
        intrinsicMatch = functionIntrinsicRegExp.search(function_source)
        if intrinsicMatch:
            intrinsic = intrinsicMatch.group(1)
            function_source = functionIntrinsicRegExp.sub("", function_source)

        overridden_name = None
        overriddenNameMatch = functionOverriddenNameRegExp.search(function_source)
        if overriddenNameMatch:
            overridden_name = overriddenNameMatch.group(1)
            function_source = functionOverriddenNameRegExp.sub("", function_source)

        if not os.getenv("CONFIGURATION", "Debug").startswith("Debug"):
            function_source = lineWithOnlySingleLineCommentRegExp.sub("", function_source)
            function_source = lineWithTrailingSingleLineCommentRegExp.sub("\n", function_source)
            function_source = leadingWhitespaceRegExp.sub("", function_source)
            function_source = multipleEmptyLinesRegExp.sub("\n", function_source)

        function_name = functionNameRegExp.findall(function_source)[0]
        async_match = functionIsAsyncRegExp.match(function_source)
        is_async = async_match != None and async_match.group(1) == "async"
        is_constructor = functionIsConstructorRegExp.match(function_source) != None
        is_getter = functionIsGetterRegExp.match(function_source) != None
        is_global_private = functionGlobalPrivateRegExp.match(function_source) != None
        parameters = [s.strip() for s in functionParameterFinder.findall(function_source)[0].split(',')]
        if len(parameters[0]) == 0:
            parameters = []

        if is_getter and not overridden_name:
            overridden_name = "\"get %s\"" % (function_name)

        if not overridden_name:
            overridden_name = "static_cast<const char*>(nullptr)"

        return BuiltinFunction(function_name, function_source, parameters, is_async, is_constructor, is_global_private, intrinsic, overridden_name)

    def __str__(self):
        interface = "%s(%s)" % (self.function_name, ', '.join(self.parameters))
        if self.is_constructor:
            interface = interface + " [Constructor]"

        if self.is_async:
            interface = "async " + interface

        return interface

    def __lt__(self, other):
        return self.function_name < other.function_name


class BuiltinsCollection:
    def __init__(self, framework_name):
        self._copyright_lines = set()
        self.objects = []
        self.framework = Framework.fromString(framework_name)
        log.debug("Created new Builtins collection.")

    def parse_builtins_file(self, filename, text):
        log.debug("Parsing builtins file: %s" % filename)

        parsed_copyrights = set(self._parse_copyright_lines(text))
        self._copyright_lines = self._copyright_lines.union(parsed_copyrights)

        log.debug("Found copyright lines:")
        for line in self._copyright_lines:
            log.debug(line)
        log.debug("")

        object_annotations = self._parse_annotations(text)

        object_name, ext = os.path.splitext(os.path.basename(filename))
        log.debug("Parsing object: %s" % object_name)

        parsed_functions = self._parse_functions(text)
        for function in parsed_functions:
            function.object = object_name

        log.debug("Parsed functions:")
        for func in parsed_functions:
            log.debug(func)
        log.debug("")

        new_object = BuiltinObject(object_name, object_annotations, parsed_functions)
        new_object.collection = self
        self.objects.append(new_object)

    def copyrights(self):
        owner_to_years = dict()
        copyrightYearRegExp = re.compile(r"(\d{4})[, ]{0,2}")
        ownerStartRegExp = re.compile(r"[^\d, ]")

        # Returns deduplicated copyrights keyed on the owner.
        for line in self._copyright_lines:
            years = set(copyrightYearRegExp.findall(line))
            ownerIndex = ownerStartRegExp.search(line).start()
            owner = line[ownerIndex:]
            log.debug("Found years: %s and owner: %s" % (years, owner))
            if owner not in owner_to_years:
                owner_to_years[owner] = set()

            owner_to_years[owner] = owner_to_years[owner].union(years)

        result = []

        for owner, years in list(owner_to_years.items()):
            sorted_years = list(years)
            sorted_years.sort()
            result.append("%s %s" % (', '.join(sorted_years), owner))

        return result

    def all_functions(self):
        result = []
        for object in self.objects:
            result.extend(object.functions)

        result.sort()
        return result

    def all_internal_functions(self):
        result = []
        for object in [o for o in self.objects if 'internal' in o.annotations]:
            result.extend(object.functions)

        result.sort()
        return result

    # Private methods.

    def _parse_copyright_lines(self, text):
        licenseBlock = multilineCommentRegExp.findall(text)[0]
        licenseBlock = licenseBlock[:licenseBlock.index("Redistribution")]

        copyrightLines = [Templates.DefaultCopyright]
        for line in licenseBlock.split("\n"):
            line = line.replace("/*", "")
            line = line.replace("*/", "")
            line = line.replace("*", "")
            line = line.replace("Copyright", "")
            line = line.replace("copyright", "")
            line = line.replace("(C)", "")
            line = line.replace("(c)", "")
            line = line.strip()

            if len(line) == 0:
                continue

            copyrightLines.append(line)

        return copyrightLines

    def _parse_annotations(self, text):
        annotations = {}

        for match in keyValueAnnotationCommentRegExp.finditer(text):
            (key, value) = match.group(1, 2)
            log.debug("Found annotation: '%s' => '%s'" % (key, value))
            if key in annotations:
                raise ParseException("Duplicate annotation found: %s" % key)

            annotations[key] = value

        for match in flagAnnotationCommentRegExp.finditer(text):
            key = match.group(1)
            log.debug("Found annotation: '%s' => 'TRUE'" % key)
            if key in annotations:
                raise ParseException("Duplicate annotation found: %s" % key)

            annotations[key] = True

        return annotations

    def _parse_functions(self, text):
        text = multilineCommentRegExp.sub("/**/", singleLineCommentRegExp.sub("//\n", text))

        matches = [func for func in functionHeadRegExp.finditer(text)]
        functionBounds = []
        start = 0
        end = 0
        for match in matches:
            start = match.start()
            if start < end:
                continue
            end = match.end()
            while text[end] != '{':
                end = end + 1
            depth = 1
            end = end + 1
            while depth > 0:
                if text[end] == '{':
                    depth = depth + 1
                elif text[end] == '}':
                    depth = depth - 1
                end = end + 1
            functionBounds.append((start, end))

        functionStrings = [text[start:end].strip() for (start, end) in functionBounds]
        return list(map(BuiltinFunction.fromString, functionStrings))
