#!/usr/bin/env python
#
# Copyright (c) 2014-2018 Apple Inc. All rights reserved.
# Copyright (c) 2014 University of Washington. 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 string
from string import Template
from operator import methodcaller

try:
    from .cpp_generator import CppGenerator
    from .cpp_generator_templates import CppGeneratorTemplates as CppTemplates
    from .generator import Generator, ucfirst
    from .models import AliasedType, ArrayType, EnumType, ObjectType
except ValueError:
    from cpp_generator import CppGenerator
    from cpp_generator_templates import CppGeneratorTemplates as CppTemplates
    from generator import Generator, ucfirst
    from models import AliasedType, ArrayType, EnumType, ObjectType

log = logging.getLogger('global')


class CppProtocolTypesImplementationGenerator(CppGenerator):
    def __init__(self, *args, **kwargs):
        CppGenerator.__init__(self, *args, **kwargs)

    def output_filename(self):
        return "%sProtocolObjects.cpp" % self.protocol_name()

    def generate_output(self):
        domains = self.domains_to_generate()
        self.calculate_types_requiring_shape_assertions(domains)

        secondary_headers = [
            '<wtf/Optional.h>',
            '<wtf/text/CString.h>',
        ]

        header_args = {
            'primaryInclude': '"%sProtocolObjects.h"' % self.protocol_name(),
            'secondaryIncludes': self._generate_secondary_header_includes(),
        }

        sections = []
        sections.append(self.generate_license())
        sections.append(Template(CppTemplates.ImplementationPrelude).substitute(None, **header_args))
        sections.append('namespace Protocol {')
        sections.extend(self._generate_enum_mapping_and_conversion_methods(domains))
        sections.append(self._generate_open_field_names())
        builder_sections = list(map(self._generate_builders_for_domain, domains))
        sections.extend([section for section in builder_sections if len(section) > 0])
        sections.append('} // namespace Protocol')
        sections.append(Template(CppTemplates.ImplementationPostlude).substitute(None, **header_args))

        return "\n\n".join(sections)

    # Private methods.

    def _generate_secondary_header_includes(self):
        header_includes = [
            (["JavaScriptCore", "WebKit"], ("WTF", "wtf/Optional.h")),
            (["JavaScriptCore", "WebKit"], ("WTF", "wtf/text/CString.h")),
        ]

        return '\n'.join(self.generate_includes_from_entries(header_includes))

    def _generate_enum_mapping(self):
        if not self.assigned_enum_values():
            return []

        lines = []
        lines.append('static const char* const enum_constant_values[] = {')
        lines.extend(['    "%s",' % enum_value for enum_value in self.assigned_enum_values()])
        lines.append('};')
        lines.append('')
        lines.append('String getEnumConstantValue(int code) {')
        lines.append('    return enum_constant_values[code];')
        lines.append('}')
        return ['\n'.join(lines)]

    def _generate_enum_conversion_methods_for_domain(self, domain):

        def type_member_is_anonymous_enum_type(type_member):
            return isinstance(type_member.type, EnumType) and type_member.type.is_anonymous

        def generate_conversion_method_body(enum_type, cpp_protocol_type):
            body_lines = []
            body_lines.extend([
                'template<>',
                'Optional<%s> parseEnumValueFromString<%s>(const String& protocolString)' % (cpp_protocol_type, cpp_protocol_type),
                '{',
                '    static const size_t constantValues[] = {',
            ])

            enum_values = enum_type.enum_values()
            for enum_value in enum_values:
                body_lines.append('        (size_t)%s::%s,' % (cpp_protocol_type, Generator.stylized_name_for_enum_value(enum_value)))

            body_lines.extend([
                '    };',
                '    for (size_t i = 0; i < %d; ++i)' % len(enum_values),
                '        if (protocolString == enum_constant_values[constantValues[i]])',
                '            return (%s)constantValues[i];' % cpp_protocol_type,
                '',
                '    return WTF::nullopt;',
                '}',
                '',
            ])
            return body_lines

        type_declarations = self.type_declarations_for_domain(domain)
        declaration_types = [decl.type for decl in type_declarations]
        object_types = [_type for _type in declaration_types if isinstance(_type, ObjectType)]
        enum_types = [_type for _type in declaration_types if isinstance(_type, EnumType)]
        if len(object_types) + len(enum_types) == 0:
            return ''

        sorted(object_types, key=methodcaller('raw_name'))
        sorted(enum_types, key=methodcaller('raw_name'))

        lines = []
        lines.append("// Enums in the '%s' Domain" % domain.domain_name)
        for enum_type in enum_types:
            cpp_protocol_type = CppGenerator.cpp_protocol_type_for_type(enum_type)
            lines.extend(generate_conversion_method_body(enum_type, cpp_protocol_type))

        for object_type in object_types:
            for enum_member in filter(type_member_is_anonymous_enum_type, object_type.members):
                cpp_protocol_type = CppGenerator.cpp_protocol_type_for_type_member(enum_member, object_type.declaration())
                lines.extend(generate_conversion_method_body(enum_member.type, cpp_protocol_type))

        if len(lines) == 1:
            return ''  # No real declarations to emit, just the domain comment.

        return self.wrap_with_guard_for_domain(domain, '\n'.join(lines))

    def _generate_enum_mapping_and_conversion_methods(self, domains):
        sections = []
        sections.append('namespace %s {' % self.helpers_namespace())
        sections.extend(self._generate_enum_mapping())
        enum_parser_sections = list(map(self._generate_enum_conversion_methods_for_domain, domains))
        sections.extend([section for section in enum_parser_sections if len(section) > 0])
        if len(sections) == 1:
            return []  # No declarations to emit, just the namespace.

        sections.append('} // namespace %s' % self.helpers_namespace())
        return sections

    def _generate_open_field_names(self):
        lines = []
        for domain in self.domains_to_generate():
            type_declarations = self.type_declarations_for_domain(domain)
            for type_declaration in [decl for decl in type_declarations if Generator.type_has_open_fields(decl.type)]:
                open_members = Generator.open_fields(type_declaration)
                for type_member in sorted(open_members, key=lambda member: member.member_name):
                    field_name = '::'.join(['Inspector', 'Protocol', domain.domain_name, ucfirst(type_declaration.type_name), ucfirst(type_member.member_name)])
                    lines.append('const char* %s = "%s";' % (field_name, type_member.member_name))

        return '\n'.join(lines)

    def _generate_builders_for_domain(self, domain):
        sections = []
        type_declarations = self.type_declarations_for_domain(domain)
        declarations_to_generate = [decl for decl in type_declarations if self.type_needs_shape_assertions(decl.type)]

        for type_declaration in declarations_to_generate:
            for type_member in type_declaration.type_members:
                if isinstance(type_member.type, EnumType):
                    sections.append(self._generate_assertion_for_enum(type_member, type_declaration))

            if isinstance(type_declaration.type, ObjectType):
                sections.append(self._generate_assertion_for_object_declaration(type_declaration))
                if Generator.type_needs_runtime_casts(type_declaration.type):
                    sections.append(self._generate_runtime_cast_for_object_declaration(type_declaration))

        return '\n\n'.join(sections)

    def _generate_runtime_cast_for_object_declaration(self, object_declaration):
        args = {
            'objectType': CppGenerator.cpp_protocol_type_for_type(object_declaration.type)
        }
        return Template(CppTemplates.ProtocolObjectRuntimeCast).substitute(None, **args)

    def _generate_assertion_for_object_declaration(self, object_declaration):
        required_members = [member for member in object_declaration.type_members if not member.is_optional]
        optional_members = [member for member in object_declaration.type_members if member.is_optional]
        should_count_properties = not Generator.type_has_open_fields(object_declaration.type)
        lines = []

        lines.append('void BindingTraits<%s>::assertValueHasExpectedType(JSON::Value* value)' % (CppGenerator.cpp_protocol_type_for_type(object_declaration.type)))
        lines.append("""{
#if ASSERT_ENABLED
    ASSERT_ARG(value, value);
    RefPtr<JSON::Object> object;
    bool castSucceeded = value->asObject(object);
    ASSERT_UNUSED(castSucceeded, castSucceeded);""")
        for type_member in required_members:
            args = {
                'memberName': type_member.member_name,
                'assertMethod': CppGenerator.cpp_assertion_method_for_type_member(type_member, object_declaration)
            }

            lines.append("""    {
        auto %(memberName)sPos = object->find("%(memberName)s"_s);
        ASSERT(%(memberName)sPos != object->end());
        %(assertMethod)s(%(memberName)sPos->value.get());
    }""" % args)

        if should_count_properties:
            lines.append('')
            lines.append('    int foundPropertiesCount = %s;' % len(required_members))

        for type_member in optional_members:
            args = {
                'memberName': type_member.member_name,
                'assertMethod': CppGenerator.cpp_assertion_method_for_type_member(type_member, object_declaration)
            }

            lines.append("""    {
        auto %(memberName)sPos = object->find("%(memberName)s"_s);
        if (%(memberName)sPos != object->end()) {
            %(assertMethod)s(%(memberName)sPos->value.get());""" % args)

            if should_count_properties:
                lines.append('            ++foundPropertiesCount;')
            lines.append('        }')
            lines.append('    }')

        if should_count_properties:
            lines.append('    if (foundPropertiesCount != object->size())')
            lines.append('        FATAL("Unexpected properties in object: %s\\n", object->toJSONString().ascii().data());')
        lines.append('#else // ASSERT_ENABLED')
        lines.append('    UNUSED_PARAM(value);')
        lines.append('#endif // ASSERT_ENABLED')
        lines.append('}')
        return '\n'.join(lines)

    def _generate_assertion_for_enum(self, enum_member, object_declaration):
        lines = []
        lines.append('void %s(JSON::Value* value)' % CppGenerator.cpp_assertion_method_for_type_member(enum_member, object_declaration))
        lines.append('{')
        lines.append('#if ASSERT_ENABLED')
        lines.append('    ASSERT_ARG(value, value);')
        lines.append('    String result;')
        lines.append('    bool castSucceeded = value->asString(result);')
        lines.append('    ASSERT(castSucceeded);')

        assert_condition = ' || '.join(['result == "%s"' % enum_value for enum_value in enum_member.type.enum_values()])
        lines.append('    ASSERT(%s);' % assert_condition)
        lines.append('#else // ASSERT_ENABLED')
        lines.append('    UNUSED_PARAM(value);')
        lines.append('#endif // ASSERT_ENABLED')
        lines.append('}')

        return '\n'.join(lines)
