# Copyright 2020 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import web_idl

from . import name_style
from .blink_v8_bridge import blink_class_name
from .code_node import EmptyNode
from .code_node import ListNode
from .code_node import TextNode
from .code_node_cxx import CxxClassDefNode
from .code_node_cxx import CxxFuncDeclNode
from .code_node_cxx import CxxFuncDefNode
from .code_node_cxx import CxxNamespaceNode
from .codegen_accumulator import CodeGenAccumulator
from .codegen_context import CodeGenContext
from .codegen_format import format_template as _format
from .codegen_utils import component_export
from .codegen_utils import component_export_header
from .codegen_utils import enclose_with_header_guard
from .codegen_utils import make_copyright_header
from .codegen_utils import make_forward_declarations
from .codegen_utils import make_header_include_directives
from .codegen_utils import write_code_node_to_file
from .mako_renderer import MakoRenderer
from .package_initializer import package_initializer
from .path_manager import PathManager
from .task_queue import TaskQueue


def make_factory_methods(cg_context):
    assert isinstance(cg_context, CodeGenContext)

    T = TextNode

    decls = ListNode()

    func_def = CxxFuncDefNode(
        name="Create",
        arg_decls=[
            "v8::Isolate* isolate",
            "v8::Local<v8::Value> value",
            "ExceptionState& exception_state",
        ],
        return_type="${class_name}",
        static=True)
    func_def.set_base_template_vars(cg_context.template_bindings())
    decls.append(func_def)

    func_def.body.extend([
        T("const auto& result = bindings::FindIndexInEnumStringTable("
          "isolate, value, string_table_, \"${enumeration.identifier}\", "
          "exception_state);"),
        T("return result.has_value() ? "
          "${class_name}(static_cast<Enum>(result.value())) : "
          "${class_name}();"),
    ])

    func_def = CxxFuncDefNode(
        name="Create",
        arg_decls=["const String& value"],
        return_type="base::Optional<${class_name}>",
        static=True)
    func_def.set_base_template_vars(cg_context.template_bindings())
    decls.append(func_def)

    func_def.body.extend([
        T("const auto& result = bindings::FindIndexInEnumStringTable"
          "(value, string_table_);"),
        T("if (!result)\n"
          "  return base::nullopt;"),
        T("return ${class_name}(static_cast<Enum>(result.value()));"),
    ])

    return decls, None


def make_constructors(cg_context):
    assert isinstance(cg_context, CodeGenContext)

    T = TextNode

    class_name = cg_context.class_name

    decls = ListNode([
        CxxFuncDeclNode(
            name=class_name,
            arg_decls=[],
            return_type="",
            constexpr=True,
            default=True),
        CxxFuncDefNode(
            name=class_name,
            arg_decls=["Enum value"],
            return_type="",
            explicit=True,
            constexpr=True,
            member_initializer_list=[
                "${base_class_name}("
                "static_cast<enum_int_t>(value), "
                "string_table_[static_cast<enum_int_t>(value)])"
            ]),
        CxxFuncDeclNode(
            name=class_name,
            arg_decls=["const ${class_name}&"],
            return_type="",
            constexpr=True,
            default=True),
        CxxFuncDeclNode(
            name=class_name,
            arg_decls=["${class_name}&&"],
            return_type="",
            constexpr=True,
            default=True),
        CxxFuncDeclNode(
            name="~${class_name}", arg_decls=[], return_type="", default=True),
    ])

    defs = ListNode([
        T("static_assert("
          "std::is_trivially_copyable<${class_name}>::value, \"\");"),
    ])
    defs.set_base_template_vars(cg_context.template_bindings())

    return decls, defs


def make_assignment_operators(cg_context):
    assert isinstance(cg_context, CodeGenContext)

    decls = ListNode([
        CxxFuncDeclNode(
            name="operator=",
            arg_decls=["const ${class_name}&"],
            return_type="${class_name}&",
            default=True),
        CxxFuncDeclNode(
            name="operator=",
            arg_decls=["${class_name}&&"],
            return_type="${class_name}&",
            default=True),
    ])
    defs = ListNode()

    # Migration adapter
    func_decl = CxxFuncDeclNode(
        name="operator=",
        arg_decls=["const String&"],
        return_type="${class_name}&")
    func_def = CxxFuncDefNode(
        name="operator=",
        arg_decls=["const String& str_value"],
        return_type="${class_name}&",
        class_name=cg_context.class_name)
    decls.append(func_decl)
    defs.append(func_def)

    func_def.set_base_template_vars(cg_context.template_bindings())
    func_def.body.append(
        TextNode("""\
const auto& index =
    bindings::FindIndexInEnumStringTable(str_value, string_table_);
CHECK(index.has_value());
return operator=(${class_name}(static_cast<Enum>(index.value())));
"""))

    return decls, defs


def make_equality_operators(cg_context):
    assert isinstance(cg_context, CodeGenContext)

    func1_def = CxxFuncDefNode(
        name="operator==",
        arg_decls=["const ${class_name}& lhs", "${class_name}::Enum rhs"],
        return_type="bool",
        inline=True)
    func1_def.set_base_template_vars(cg_context.template_bindings())
    func1_def.body.append(TextNode("return lhs.AsEnum() == rhs;"))

    func2_def = CxxFuncDefNode(
        name="operator==",
        arg_decls=["${class_name}::Enum lhs", "const ${class_name}& rhs"],
        return_type="bool",
        inline=True)
    func2_def.set_base_template_vars(cg_context.template_bindings())
    func2_def.body.append(TextNode("return lhs == rhs.AsEnum();"))

    decls = ListNode([func1_def, EmptyNode(), func2_def])

    return decls, None


def make_as_enum_function(cg_context):
    assert isinstance(cg_context, CodeGenContext)

    func_def = CxxFuncDefNode(
        name="AsEnum", arg_decls=[], return_type="Enum", const=True)
    func_def.body.append(TextNode("return static_cast<Enum>(GetEnumValue());"))

    return func_def, None


def make_nested_enum_class_def(cg_context):
    assert isinstance(cg_context, CodeGenContext)

    enum_values = [
        TextNode(name_style.constant(value))
        for value in cg_context.enumeration.values
    ]

    return ListNode([
        TextNode("enum class Enum : enum_int_t {"),
        ListNode(enum_values, separator=", "),
        TextNode("};"),
    ])


def make_enum_string_table(cg_context):
    assert isinstance(cg_context, CodeGenContext)

    str_values = [
        TextNode("\"{}\"".format(value))
        for value in cg_context.enumeration.values
    ]

    decls = ListNode([
        TextNode("static constexpr const char* const string_table_[] = {"),
        ListNode(str_values, separator=", "),
        TextNode("};"),
    ])

    defs = TextNode("const char* const ${class_name}::string_table_[];")
    defs.set_base_template_vars(cg_context.template_bindings())

    return decls, defs


def generate_enumeration(enumeration_identifier):
    assert isinstance(enumeration_identifier, web_idl.Identifier)

    web_idl_database = package_initializer().web_idl_database()
    enumeration = web_idl_database.find(enumeration_identifier)

    path_manager = PathManager(enumeration)
    assert path_manager.api_component == path_manager.impl_component
    api_component = path_manager.api_component
    for_testing = enumeration.code_generator_info.for_testing

    # Class names
    class_name = blink_class_name(enumeration)

    cg_context = CodeGenContext(
        enumeration=enumeration,
        class_name=class_name,
        base_class_name="bindings::EnumerationBase")

    # Filepaths
    header_path = path_manager.api_path(ext="h")
    source_path = path_manager.api_path(ext="cc")

    # Root nodes
    header_node = ListNode(tail="\n")
    header_node.set_accumulator(CodeGenAccumulator())
    header_node.set_renderer(MakoRenderer())
    source_node = ListNode(tail="\n")
    source_node.set_accumulator(CodeGenAccumulator())
    source_node.set_renderer(MakoRenderer())

    # Namespaces
    header_blink_ns = CxxNamespaceNode(name_style.namespace("blink"))
    source_blink_ns = CxxNamespaceNode(name_style.namespace("blink"))

    # Class definition
    class_def = CxxClassDefNode(cg_context.class_name,
                                base_class_names=["bindings::EnumerationBase"],
                                final=True,
                                export=component_export(
                                    api_component, for_testing))
    class_def.set_base_template_vars(cg_context.template_bindings())

    # Implementation parts
    factory_decls, factory_defs = make_factory_methods(cg_context)
    ctor_decls, ctor_defs = make_constructors(cg_context)
    assign_decls, assign_defs = make_assignment_operators(cg_context)
    equal_decls, equal_defs = make_equality_operators(cg_context)
    nested_enum_class_def = make_nested_enum_class_def(cg_context)
    table_decls, table_defs = make_enum_string_table(cg_context)
    as_enum_decl, as_enum_def = make_as_enum_function(cg_context)

    # Header part (copyright, include directives, and forward declarations)
    header_node.extend([
        make_copyright_header(),
        EmptyNode(),
        enclose_with_header_guard(
            ListNode([
                make_header_include_directives(header_node.accumulator),
                EmptyNode(),
                header_blink_ns,
            ]), name_style.header_guard(header_path)),
    ])
    header_blink_ns.body.extend([
        make_forward_declarations(header_node.accumulator),
        EmptyNode(),
    ])
    source_node.extend([
        make_copyright_header(),
        EmptyNode(),
        TextNode("#include \"{}\"".format(header_path)),
        EmptyNode(),
        make_header_include_directives(source_node.accumulator),
        EmptyNode(),
        source_blink_ns,
    ])
    source_blink_ns.body.extend([
        make_forward_declarations(source_node.accumulator),
        EmptyNode(),
    ])

    # Assemble the parts.
    header_node.accumulator.add_include_headers([
        component_export_header(api_component, for_testing),
        "third_party/blink/renderer/bindings/core/v8/generated_code_helper.h",
        "third_party/blink/renderer/platform/bindings/enumeration_base.h",
    ])

    header_blink_ns.body.append(class_def)
    header_blink_ns.body.append(EmptyNode())

    class_def.public_section.append(nested_enum_class_def)
    class_def.public_section.append(EmptyNode())

    class_def.public_section.append(factory_decls)
    class_def.public_section.append(EmptyNode())
    source_blink_ns.body.append(factory_defs)
    source_blink_ns.body.append(EmptyNode())

    class_def.private_section.append(table_decls)
    class_def.private_section.append(EmptyNode())
    source_blink_ns.body.append(table_defs)
    source_blink_ns.body.append(EmptyNode())

    class_def.public_section.append(ctor_decls)
    class_def.public_section.append(EmptyNode())
    source_blink_ns.body.append(ctor_defs)
    source_blink_ns.body.append(EmptyNode())

    class_def.public_section.append(assign_decls)
    class_def.public_section.append(EmptyNode())
    source_blink_ns.body.append(assign_defs)
    source_blink_ns.body.append(EmptyNode())

    class_def.public_section.append(as_enum_decl)
    class_def.public_section.append(EmptyNode())
    source_blink_ns.body.append(as_enum_def)
    source_blink_ns.body.append(EmptyNode())

    header_blink_ns.body.append(equal_decls)
    header_blink_ns.body.append(EmptyNode())
    source_blink_ns.body.append(equal_defs)
    source_blink_ns.body.append(EmptyNode())

    # Write down to the files.
    write_code_node_to_file(header_node, path_manager.gen_path_to(header_path))
    write_code_node_to_file(source_node, path_manager.gen_path_to(source_path))


def generate_enumerations(task_queue):
    assert isinstance(task_queue, TaskQueue)

    web_idl_database = package_initializer().web_idl_database()

    for enumeration in web_idl_database.enumerations:
        task_queue.post_task(generate_enumeration, enumeration.identifier)
