#!/usr/bin/env python
#
# Copyright (c) 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 string
from string import Template

try:
    from .generator import Generator
    from .models import EnumType, ObjectType, ArrayType, AliasedType, PrimitiveType, Frameworks
    from .objc_generator import ObjCGenerator
    from .objc_generator_templates import ObjCGeneratorTemplates as ObjCTemplates
except ValueError:
    from generator import Generator
    from models import EnumType, ObjectType, ArrayType, AliasedType, PrimitiveType, Frameworks
    from objc_generator import ObjCGenerator
    from objc_generator_templates import ObjCGeneratorTemplates as ObjCTemplates

log = logging.getLogger('global')


def add_newline(lines):
    if lines and lines[-1] == '':
        return
    lines.append('')


class ObjCProtocolTypeConversionsImplementationGenerator(ObjCGenerator):
    def __init__(self, *args, **kwargs):
        ObjCGenerator.__init__(self, *args, **kwargs)

    def output_filename(self):
        return '%sTypeConversions.mm' % self.protocol_name()

    def domains_to_generate(self):
        return list(filter(self.should_generate_types_for_domain, Generator.domains_to_generate(self)))

    def generate_output(self):
        secondary_headers = [
            '"%s.h"' % self.protocol_name(),
            '"%sTypeParser.h"' % self.protocol_name(),
            Generator.string_for_file_include('%sJSONObjectPrivate.h' % ObjCGenerator.OBJC_STATIC_PREFIX, Frameworks.WebInspector, self.model().framework),
        ]
        secondary_headers.sort()

        header_args = {
            'primaryInclude': '"%sTypeConversions.h"' % self.protocol_name(),
            'secondaryIncludes': '\n'.join(['#import ' + header for header in secondary_headers]),
        }

        domains = self.domains_to_generate()
        sections = []
        sections.append(self.generate_license())
        sections.append(Template(ObjCTemplates.ImplementationPrelude).substitute(None, **header_args))
        sections.append(self._generate_type_factory_category_interface(domains))
        sections.append(self._generate_type_factory_category_implementation(domains))
        sections.append(Template(ObjCTemplates.ImplementationPostlude).substitute(None, **header_args))
        return '\n\n'.join(sections)

    def _generate_type_factory_category_interface(self, domains):
        lines = []
        for domain in domains:
            lines.append('@interface %sTypeConversions (%sDomain)' % (self.protocol_name(), domain.domain_name))
            lines.append('')

            for declaration in self.type_declarations_for_domain(domain):
                lines.append(self._generate_type_factory_method_declaration(domain, declaration))

            add_newline(lines)
            lines.append('@end')

        return '\n'.join(lines)

    def _generate_type_factory_method_declaration(self, domain, declaration):
        resolved_type = declaration.type
        if isinstance(resolved_type, AliasedType):
            resolved_type = resolved_type.aliased_type
        if isinstance(resolved_type, (ObjectType, ArrayType, PrimitiveType)):
            objc_type = self.objc_class_for_type(resolved_type)
            return '+ (void)_parse%s:(%s **)outValue fromPayload:(id)payload;' % (declaration.type.raw_name(), objc_type)
        if isinstance(resolved_type, EnumType):
            return '+ (void)_parse%s:(NSNumber **)outValue fromPayload:(id)payload;' % declaration.type.raw_name()

    def _generate_type_factory_category_implementation(self, domains):
        lines = []
        for domain in domains:
            lines.append('@implementation %sTypeConversions (%sDomain)' % (self.protocol_name(), domain.domain_name))
            lines.append('')

            for declaration in self.type_declarations_for_domain(domain):
                lines.append(self._generate_type_factory_method_implementation(domain, declaration))
                add_newline(lines)
            lines.append('@end')
        return '\n'.join(lines)

    def _generate_type_factory_method_implementation(self, domain, declaration):
        lines = []
        resolved_type = declaration.type
        if isinstance(resolved_type, AliasedType):
            resolved_type = resolved_type.aliased_type

        objc_class = self.objc_class_for_type(resolved_type)
        if isinstance(resolved_type, (ObjectType, ArrayType, PrimitiveType)):
            lines.append('+ (void)_parse%s:(%s **)outValue fromPayload:(id)payload' % (declaration.type.raw_name(), objc_class))
        if isinstance(resolved_type, EnumType):
            lines.append('+ (void)_parse%s:(NSNumber **)outValue fromPayload:(id)payload' % declaration.type.raw_name())

        lines.append('{')
        if isinstance(resolved_type, EnumType):
            lines.append('    THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSString class]);')
            lines.append('    Optional<%(type)s> result = Inspector::fromProtocolString<%(type)s>(payload);' % {'type': self.objc_name_for_type(resolved_type)})
            lines.append('    THROW_EXCEPTION_FOR_BAD_ENUM_VALUE(result, @"%s");' % declaration.type.raw_name())
            lines.append('    *outValue = @(result.value());')
        elif isinstance(resolved_type, (ArrayType, PrimitiveType)):
            lines.append('    THROW_EXCEPTION_FOR_BAD_TYPE(payload, [%s class]);' % objc_class)
            lines.append('    *outValue = (%s *)payload;' % objc_class)
        elif isinstance(resolved_type, ObjectType):
            lines.append('    THROW_EXCEPTION_FOR_BAD_TYPE(payload, [NSDictionary class]);')
            lines.append('    *outValue = [[%s alloc] initWithPayload:payload];' % (objc_class))
        lines.append('}')
        return '\n'.join(lines)
