# Copyright 2016 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 os.path
import sys
import optparse
import collections
import functools
import re
import copy
try:
    import json
except ImportError:
    import simplejson as json

import pdl

# Path handling for libraries and templates
# Paths have to be normalized because Jinja uses the exact template path to
# determine the hash used in the cache filename, and we need a pre-caching step
# to be concurrency-safe. Use absolute path because __file__ is absolute if
# module is imported, and relative if executed directly.
# If paths differ between pre-caching and individual file compilation, the cache
# is regenerated, which causes a race condition and breaks concurrent build,
# since some compile processes will try to read the partially written cache.
module_path, module_filename = os.path.split(os.path.realpath(__file__))

def read_config():
    # pylint: disable=W0703
    def json_to_object(data, output_base, config_base):
        def json_object_hook(object_dict):
            items = [(k, os.path.join(config_base, v) if k == "path" else v) for (k, v) in object_dict.items()]
            items = [(k, os.path.join(output_base, v) if k == "output" else v) for (k, v) in items]
            keys, values = zip(*items)
            return collections.namedtuple('X', keys)(*values)
        return json.loads(data, object_hook=json_object_hook)

    def init_defaults(config_tuple, path, defaults):
        keys = list(config_tuple._fields)  # pylint: disable=E1101
        values = [getattr(config_tuple, k) for k in keys]
        for i in xrange(len(keys)):
            if hasattr(values[i], "_fields"):
                values[i] = init_defaults(values[i], path + "." + keys[i], defaults)
        for optional in defaults:
            if optional.find(path + ".") != 0:
                continue
            optional_key = optional[len(path) + 1:]
            if optional_key.find(".") == -1 and optional_key not in keys:
                keys.append(optional_key)
                values.append(defaults[optional])
        return collections.namedtuple('X', keys)(*values)

    try:
        cmdline_parser = optparse.OptionParser()
        cmdline_parser.add_option("--output_base")
        cmdline_parser.add_option("--jinja_dir")
        cmdline_parser.add_option("--config")
        cmdline_parser.add_option("--config_value", action="append", type="string")
        arg_options, _ = cmdline_parser.parse_args()
        jinja_dir = arg_options.jinja_dir
        if not jinja_dir:
            raise Exception("jinja directory must be specified")
        jinja_dir = jinja_dir.decode('utf8')
        output_base = arg_options.output_base
        if not output_base:
            raise Exception("Base output directory must be specified")
        output_base = output_base.decode('utf8')
        config_file = arg_options.config
        if not config_file:
            raise Exception("Config file name must be specified")
        config_file = config_file.decode('utf8')
        config_base = os.path.dirname(config_file)
        config_values = arg_options.config_value
        if not config_values:
            config_values = []
    except Exception:
        # Work with python 2 and 3 http://docs.python.org/py3k/howto/pyporting.html
        exc = sys.exc_info()[1]
        sys.stderr.write("Failed to parse command-line arguments: %s\n\n" % exc)
        exit(1)

    try:
        config_json_file = open(config_file, "r")
        config_json_string = config_json_file.read()
        config_partial = json_to_object(config_json_string, output_base, config_base)
        config_json_file.close()
        defaults = {
            ".use_snake_file_names": False,
            ".use_title_case_methods": False,
            ".imported": False,
            ".imported.export_macro": "",
            ".imported.export_header": False,
            ".imported.header": False,
            ".imported.package": False,
            ".imported.options": False,
            ".protocol.export_macro": "",
            ".protocol.export_header": False,
            ".protocol.options": False,
            ".protocol.file_name_prefix": "",
            ".exported": False,
            ".exported.export_macro": "",
            ".exported.export_header": False,
            ".lib": False,
            ".lib.export_macro": "",
            ".lib.export_header": False,
        }
        for key_value in config_values:
            parts = key_value.split("=")
            if len(parts) == 2:
                defaults["." + parts[0]] = parts[1]
        return (jinja_dir, config_file, init_defaults(config_partial, "", defaults))
    except Exception:
        # Work with python 2 and 3 http://docs.python.org/py3k/howto/pyporting.html
        exc = sys.exc_info()[1]
        sys.stderr.write("Failed to parse config file: %s\n\n" % exc)
        exit(1)


# ---- Begin of utilities exposed to generator ----


def to_title_case(name):
    return name[:1].upper() + name[1:]


def dash_to_camelcase(word):
    prefix = ""
    if word[0] == "-":
        prefix = "Negative"
        word = word[1:]
    return prefix + "".join(to_title_case(x) or "-" for x in word.split("-"))


def to_snake_case(name):
    return re.sub(r"([a-z0-9])([A-Z])", r"\1_\2", name, sys.maxint).lower()


def to_method_case(config, name):
    if config.use_title_case_methods:
        return to_title_case(name)
    return name


def join_arrays(dict, keys):
    result = []
    for key in keys:
        if key in dict:
            result += dict[key]
    return result


def format_include(config, header, file_name=None):
    if file_name is not None:
        header = header + "/" + file_name + ".h"
    header = "\"" + header + "\"" if header[0] not in "<\"" else header
    if config.use_snake_file_names:
        header = to_snake_case(header)
    return header


def format_domain_include(config, header, file_name):
    return format_include(config, header, config.protocol.file_name_prefix + file_name)


def to_file_name(config, file_name):
    if config.use_snake_file_names:
        return to_snake_case(file_name).replace(".cpp", ".cc")
    return file_name


# ---- End of utilities exposed to generator ----


def initialize_jinja_env(jinja_dir, cache_dir, config):
    # pylint: disable=F0401
    sys.path.insert(1, os.path.abspath(jinja_dir))
    import jinja2

    jinja_env = jinja2.Environment(
        loader=jinja2.FileSystemLoader(module_path),
        # Bytecode cache is not concurrency-safe unless pre-cached:
        # if pre-cached this is read-only, but writing creates a race condition.
        bytecode_cache=jinja2.FileSystemBytecodeCache(cache_dir),
        keep_trailing_newline=True,  # newline-terminate generated files
        lstrip_blocks=True,  # so can indent control flow tags
        trim_blocks=True)
    jinja_env.filters.update({"to_title_case": to_title_case, "dash_to_camelcase": dash_to_camelcase, "to_method_case": functools.partial(to_method_case, config)})
    jinja_env.add_extension("jinja2.ext.loopcontrols")
    return jinja_env


def create_imported_type_definition(domain_name, type, imported_namespace):
    # pylint: disable=W0622
    return {
        "return_type": "std::unique_ptr<%s::%s::API::%s>" % (imported_namespace, domain_name, type["id"]),
        "pass_type": "std::unique_ptr<%s::%s::API::%s>" % (imported_namespace, domain_name, type["id"]),
        "to_raw_type": "%s.get()",
        "to_pass_type": "std::move(%s)",
        "to_rvalue": "std::move(%s)",
        "type": "std::unique_ptr<%s::%s::API::%s>" % (imported_namespace, domain_name, type["id"]),
        "raw_type": "%s::%s::API::%s" % (imported_namespace, domain_name, type["id"]),
        "raw_pass_type": "%s::%s::API::%s*" % (imported_namespace, domain_name, type["id"]),
        "raw_return_type": "%s::%s::API::%s*" % (imported_namespace, domain_name, type["id"]),
    }


def create_user_type_definition(domain_name, type):
    # pylint: disable=W0622
    return {
        "return_type": "std::unique_ptr<protocol::%s::%s>" % (domain_name, type["id"]),
        "pass_type": "std::unique_ptr<protocol::%s::%s>" % (domain_name, type["id"]),
        "to_raw_type": "%s.get()",
        "to_pass_type": "std::move(%s)",
        "to_rvalue": "std::move(%s)",
        "type": "std::unique_ptr<protocol::%s::%s>" % (domain_name, type["id"]),
        "raw_type": "protocol::%s::%s" % (domain_name, type["id"]),
        "raw_pass_type": "protocol::%s::%s*" % (domain_name, type["id"]),
        "raw_return_type": "protocol::%s::%s*" % (domain_name, type["id"]),
    }


def create_object_type_definition():
    # pylint: disable=W0622
    return {
        "return_type": "std::unique_ptr<protocol::DictionaryValue>",
        "pass_type": "std::unique_ptr<protocol::DictionaryValue>",
        "to_raw_type": "%s.get()",
        "to_pass_type": "std::move(%s)",
        "to_rvalue": "std::move(%s)",
        "type": "std::unique_ptr<protocol::DictionaryValue>",
        "raw_type": "protocol::DictionaryValue",
        "raw_pass_type": "protocol::DictionaryValue*",
        "raw_return_type": "protocol::DictionaryValue*",
    }


def create_any_type_definition():
    # pylint: disable=W0622
    return {
        "return_type": "std::unique_ptr<protocol::Value>",
        "pass_type": "std::unique_ptr<protocol::Value>",
        "to_raw_type": "%s.get()",
        "to_pass_type": "std::move(%s)",
        "to_rvalue": "std::move(%s)",
        "type": "std::unique_ptr<protocol::Value>",
        "raw_type": "protocol::Value",
        "raw_pass_type": "protocol::Value*",
        "raw_return_type": "protocol::Value*",
    }


def create_string_type_definition():
    # pylint: disable=W0622
    return {
        "return_type": "String",
        "pass_type": "const String&",
        "to_pass_type": "%s",
        "to_raw_type": "%s",
        "to_rvalue": "%s",
        "type": "String",
        "raw_type": "String",
        "raw_pass_type": "const String&",
        "raw_return_type": "String",
    }


def create_primitive_type_definition(type):
    # pylint: disable=W0622
    typedefs = {
        "number": "double",
        "integer": "int",
        "boolean": "bool"
    }
    defaults = {
        "number": "0",
        "integer": "0",
        "boolean": "false"
    }
    jsontypes = {
        "number": "TypeDouble",
        "integer": "TypeInteger",
        "boolean": "TypeBoolean",
    }
    return {
        "return_type": typedefs[type],
        "pass_type": typedefs[type],
        "to_pass_type": "%s",
        "to_raw_type": "%s",
        "to_rvalue": "%s",
        "type": typedefs[type],
        "raw_type": typedefs[type],
        "raw_pass_type": typedefs[type],
        "raw_return_type": typedefs[type],
        "default_value": defaults[type]
    }


def wrap_array_definition(type):
    # pylint: disable=W0622
    return {
        "return_type": "std::unique_ptr<protocol::Array<%s>>" % type["raw_type"],
        "pass_type": "std::unique_ptr<protocol::Array<%s>>" % type["raw_type"],
        "to_raw_type": "%s.get()",
        "to_pass_type": "std::move(%s)",
        "to_rvalue": "std::move(%s)",
        "type": "std::unique_ptr<protocol::Array<%s>>" % type["raw_type"],
        "raw_type": "protocol::Array<%s>" % type["raw_type"],
        "raw_pass_type": "protocol::Array<%s>*" % type["raw_type"],
        "raw_return_type": "protocol::Array<%s>*" % type["raw_type"],
        "out_type": "protocol::Array<%s>&" % type["raw_type"],
    }


class Protocol(object):
    def __init__(self, config):
        self.config = config
        self.json_api = {"domains": []}
        self.imported_domains = []
        self.exported_domains = []
        self.generate_domains = self.read_protocol_file(config.protocol.path)

        if config.protocol.options:
            self.generate_domains = [rule.domain for rule in config.protocol.options]
            self.exported_domains = [rule.domain for rule in config.protocol.options if hasattr(rule, "exported")]

        if config.imported:
            self.imported_domains = self.read_protocol_file(config.imported.path)
            if config.imported.options:
                self.imported_domains = [rule.domain for rule in config.imported.options]

        self.patch_full_qualified_refs()
        self.create_notification_types()
        self.create_type_definitions()
        self.generate_used_types()


    def read_protocol_file(self, file_name):
        input_file = open(file_name, "r")
        parsed_json = pdl.loads(input_file.read(), file_name)
        input_file.close()
        version = parsed_json["version"]["major"] + "." + parsed_json["version"]["minor"]
        domains = []
        for domain in parsed_json["domains"]:
            domains.append(domain["domain"])
            domain["version"] = version
        self.json_api["domains"] += parsed_json["domains"]
        return domains


    def patch_full_qualified_refs(self):
        def patch_full_qualified_refs_in_domain(json, domain_name):
            if isinstance(json, list):
                for item in json:
                    patch_full_qualified_refs_in_domain(item, domain_name)
            if not isinstance(json, dict):
                return
            for key in json:
                if key == "type" and json[key] == "string":
                    json[key] = domain_name + ".string"
                if key != "$ref":
                    patch_full_qualified_refs_in_domain(json[key], domain_name)
                    continue
                if json["$ref"].find(".") == -1:
                    json["$ref"] = domain_name + "." + json["$ref"]
            return

        for domain in self.json_api["domains"]:
            patch_full_qualified_refs_in_domain(domain, domain["domain"])


    def all_references(self, json):
        refs = set()
        if isinstance(json, list):
            for item in json:
                refs |= self.all_references(item)
        if not isinstance(json, dict):
            return refs
        for key in json:
            if key != "$ref":
                refs |= self.all_references(json[key])
            else:
                refs.add(json["$ref"])
        return refs

    def generate_used_types(self):
        all_refs = set()
        for domain in self.json_api["domains"]:
            domain_name = domain["domain"]
            if "commands" in domain:
                for command in domain["commands"]:
                    if self.generate_command(domain_name, command["name"]):
                        all_refs |= self.all_references(command)
            if "events" in domain:
                for event in domain["events"]:
                    if self.generate_event(domain_name, event["name"]):
                        all_refs |= self.all_references(event)
                        all_refs.add(domain_name + "." + to_title_case(event["name"]) + "Notification")

        dependencies = self.generate_type_dependencies()
        queue = set(all_refs)
        while len(queue):
            ref = queue.pop()
            if ref in dependencies:
                queue |= dependencies[ref] - all_refs
                all_refs |= dependencies[ref]
        self.used_types = all_refs


    def generate_type_dependencies(self):
        dependencies = dict()
        domains_with_types = (x for x in self.json_api["domains"] if "types" in x)
        for domain in domains_with_types:
            domain_name = domain["domain"]
            for type in domain["types"]:
                related_types = self.all_references(type)
                if len(related_types):
                    dependencies[domain_name + "." + type["id"]] = related_types
        return dependencies


    def create_notification_types(self):
        for domain in self.json_api["domains"]:
            if "events" in domain:
                for event in domain["events"]:
                    event_type = dict()
                    event_type["description"] = "Wrapper for notification params"
                    event_type["type"] = "object"
                    event_type["id"] = to_title_case(event["name"]) + "Notification"
                    if "parameters" in event:
                        event_type["properties"] = copy.deepcopy(event["parameters"])
                    if "types" not in domain:
                        domain["types"] = list()
                    domain["types"].append(event_type)


    def create_type_definitions(self):
        imported_namespace = "::".join(self.config.imported.namespace) if self.config.imported else ""
        self.type_definitions = {}
        self.type_definitions["number"] = create_primitive_type_definition("number")
        self.type_definitions["integer"] = create_primitive_type_definition("integer")
        self.type_definitions["boolean"] = create_primitive_type_definition("boolean")
        self.type_definitions["object"] = create_object_type_definition()
        self.type_definitions["any"] = create_any_type_definition()
        for domain in self.json_api["domains"]:
            self.type_definitions[domain["domain"] + ".string"] = create_string_type_definition()
            if not ("types" in domain):
                continue
            for type in domain["types"]:
                type_name = domain["domain"] + "." + type["id"]
                if type["type"] == "object" and domain["domain"] in self.imported_domains:
                    self.type_definitions[type_name] = create_imported_type_definition(domain["domain"], type, imported_namespace)
                elif type["type"] == "object":
                    self.type_definitions[type_name] = create_user_type_definition(domain["domain"], type)
                elif type["type"] == "array":
                    items_type = type["items"]["type"]
                    self.type_definitions[type_name] = wrap_array_definition(self.type_definitions[items_type])
                elif type["type"] == domain["domain"] + ".string":
                    self.type_definitions[type_name] = create_string_type_definition()
                else:
                    self.type_definitions[type_name] = create_primitive_type_definition(type["type"])


    def check_options(self, options, domain, name, include_attr, exclude_attr, default):
        for rule in options:
            if rule.domain != domain:
                continue
            if include_attr and hasattr(rule, include_attr):
                return name in getattr(rule, include_attr)
            if exclude_attr and hasattr(rule, exclude_attr):
                return name not in getattr(rule, exclude_attr)
            return default
        return False


    # ---- Begin of methods exposed to generator


    def type_definition(self, name):
        return self.type_definitions[name]


    def resolve_type(self, prop):
        if "$ref" in prop:
            return self.type_definitions[prop["$ref"]]
        if prop["type"] == "array":
            return wrap_array_definition(self.resolve_type(prop["items"]))
        return self.type_definitions[prop["type"]]


    def generate_command(self, domain, command):
        if not self.config.protocol.options:
            return domain in self.generate_domains
        return self.check_options(self.config.protocol.options, domain, command, "include", "exclude", True)


    def generate_event(self, domain, event):
        if not self.config.protocol.options:
            return domain in self.generate_domains
        return self.check_options(self.config.protocol.options, domain, event, "include_events", "exclude_events", True)


    def generate_type(self, domain, typename):
        return domain + "." + typename in self.used_types


    def is_async_command(self, domain, command):
        if not self.config.protocol.options:
            return False
        return self.check_options(self.config.protocol.options, domain, command, "async", None, False)


    def is_exported(self, domain, name):
        if not self.config.protocol.options:
            return False
        return self.check_options(self.config.protocol.options, domain, name, "exported", None, False)


    def is_imported(self, domain, name):
        if not self.config.imported:
            return False
        if not self.config.imported.options:
            return domain in self.imported_domains
        return self.check_options(self.config.imported.options, domain, name, "imported", None, False)


    def is_exported_domain(self, domain):
        return domain in self.exported_domains


    def generate_disable(self, domain):
        if "commands" not in domain:
            return True
        for command in domain["commands"]:
            if command["name"] == "disable" and self.generate_command(domain["domain"], "disable"):
                return False
        return True


    def is_imported_dependency(self, domain):
        return domain in self.generate_domains or domain in self.imported_domains


def main():
    jinja_dir, config_file, config = read_config()

    protocol = Protocol(config)

    if not config.exported and len(protocol.exported_domains):
        sys.stderr.write("Domains [%s] are exported, but config is missing export entry\n\n" % ", ".join(protocol.exported_domains))
        exit(1)

    if not os.path.exists(config.protocol.output):
        os.mkdir(config.protocol.output)
    if len(protocol.exported_domains) and not os.path.exists(config.exported.output):
        os.mkdir(config.exported.output)
    jinja_env = initialize_jinja_env(jinja_dir, config.protocol.output, config)

    inputs = []
    inputs.append(__file__)
    inputs.append(config_file)
    inputs.append(config.protocol.path)
    if config.imported:
        inputs.append(config.imported.path)
    templates_dir = os.path.join(module_path, "templates")
    inputs.append(os.path.join(templates_dir, "TypeBuilder_h.template"))
    inputs.append(os.path.join(templates_dir, "TypeBuilder_cpp.template"))
    inputs.append(os.path.join(templates_dir, "Exported_h.template"))
    inputs.append(os.path.join(templates_dir, "Imported_h.template"))

    h_template = jinja_env.get_template("templates/TypeBuilder_h.template")
    cpp_template = jinja_env.get_template("templates/TypeBuilder_cpp.template")
    exported_template = jinja_env.get_template("templates/Exported_h.template")
    imported_template = jinja_env.get_template("templates/Imported_h.template")

    outputs = dict()

    for domain in protocol.json_api["domains"]:
        class_name = domain["domain"]
        file_name = config.protocol.file_name_prefix + class_name
        template_context = {
            "protocol": protocol,
            "config": config,
            "domain": domain,
            "join_arrays": join_arrays,
            "format_include": functools.partial(format_include, config),
            "format_domain_include": functools.partial(format_domain_include, config),
        }

        if domain["domain"] in protocol.generate_domains:
            outputs[os.path.join(config.protocol.output, to_file_name(config, file_name + ".h"))] = h_template.render(template_context)
            outputs[os.path.join(config.protocol.output, to_file_name(config, file_name + ".cpp"))] = cpp_template.render(template_context)
            if domain["domain"] in protocol.exported_domains:
                outputs[os.path.join(config.exported.output, to_file_name(config, file_name + ".h"))] = exported_template.render(template_context)
        if domain["domain"] in protocol.imported_domains:
            outputs[os.path.join(config.protocol.output, to_file_name(config, file_name + ".h"))] = imported_template.render(template_context)

    if config.lib:
        template_context = {
            "config": config,
            "format_include": functools.partial(format_include, config),
        }

        lib_templates_dir = os.path.join(module_path, "lib")
        # Note these should be sorted in the right order.
        # TODO(dgozman): sort them programmatically based on commented includes.
        lib_h_templates = [
            "Collections_h.template",
            "ErrorSupport_h.template",
            "Values_h.template",
            "Object_h.template",
            "ValueConversions_h.template",
            "Maybe_h.template",
            "Array_h.template",
            "DispatcherBase_h.template",
            "Parser_h.template",
        ]

        lib_cpp_templates = [
            "Protocol_cpp.template",
            "ErrorSupport_cpp.template",
            "Values_cpp.template",
            "Object_cpp.template",
            "DispatcherBase_cpp.template",
            "Parser_cpp.template",
        ]

        forward_h_templates = [
            "Forward_h.template",
            "Allocator_h.template",
            "FrontendChannel_h.template",
        ]

        def generate_lib_file(file_name, template_files):
            parts = []
            for template_file in template_files:
                inputs.append(os.path.join(lib_templates_dir, template_file))
                template = jinja_env.get_template("lib/" + template_file)
                parts.append(template.render(template_context))
            outputs[file_name] = "\n\n".join(parts)

        generate_lib_file(os.path.join(config.lib.output, to_file_name(config, "Forward.h")), forward_h_templates)
        generate_lib_file(os.path.join(config.lib.output, to_file_name(config, "Protocol.h")), lib_h_templates)
        generate_lib_file(os.path.join(config.lib.output, to_file_name(config, "Protocol.cpp")), lib_cpp_templates)

    # Make gyp / make generatos happy, otherwise make rebuilds world.
    inputs_ts = max(map(os.path.getmtime, inputs))
    up_to_date = True
    for output_file in outputs.iterkeys():
        if not os.path.exists(output_file) or os.path.getmtime(output_file) < inputs_ts:
            up_to_date = False
            break
    if up_to_date:
        sys.exit()

    for file_name, content in outputs.iteritems():
        out_file = open(file_name, "w")
        out_file.write(content)
        out_file.close()


main()
