#!/usr/bin/env python
# Copyright (c) 2011 Google Inc. All rights reserved.
# Copyright (c) 2012 Intel Corporation. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#     * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#     * 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.
#     * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
# OWNER OR 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 os.path
import sys
import string
import optparse
import re
try:
    import json
except ImportError:
    import simplejson as json

cmdline_parser = optparse.OptionParser()
cmdline_parser.add_option("--output_js_dir")

try:
    arg_options, arg_values = cmdline_parser.parse_args()
    if (len(arg_values) != 1):
        raise Exception("Exactly one plain argument expected (found %s)" % len(arg_values))
    input_json_filename = arg_values[0]
    output_js_dirname = arg_options.output_js_dir
    if not output_js_dirname:
        raise Exception("Output .js directory must be specified")
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)
    sys.stderr.write("Usage: <script> some.json --output_js_dir <output_js_dir>\n")
    exit(1)


def fix_camel_case(name):
    prefix = ""
    if name[0] == "-":
        prefix = "Negative"
        name = name[1:]
    refined = re.sub(r'-(\w)', lambda pat: pat.group(1).upper(), name)
    refined = to_title_case(refined)
    return prefix + re.sub(r'(?i)HTML|XML|WML|API', lambda pat: pat.group(0).upper(), refined)


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


class RawTypes(object):

    @staticmethod
    def get_js(json_type):
        if json_type == "boolean":
            return "boolean"
        elif json_type == "string":
            return "string"
        elif json_type == "array":
            return "object"
        elif json_type == "object":
            return "object"
        elif json_type == "integer":
            return "number"
        elif json_type == "number":
            return "number"
        elif json_type == "any":
            raise Exception("Unsupported")
        else:
            raise Exception("Unknown type: %s" % json_type)


class TypeData(object):

    def __init__(self, json_type):
        if "type" not in json_type:
            raise Exception("Unknown type")
        json_type_name = json_type["type"]
        self.raw_type_js_ = RawTypes.get_js(json_type_name)

    def get_raw_type_js(self):
        return self.raw_type_js_


class TypeMap:

    def __init__(self, api):
        self.map_ = {}
        for json_domain in api["domains"]:
            domain_name = json_domain["domain"]

            domain_map = {}
            self.map_[domain_name] = domain_map

            if "types" in json_domain:
                for json_type in json_domain["types"]:
                    type_name = json_type["id"]
                    type_data = TypeData(json_type)
                    domain_map[type_name] = type_data

    def get(self, domain_name, type_name):
        return self.map_[domain_name][type_name]


def resolve_param_raw_type_js(json_parameter, scope_domain_name):
    if "$ref" in json_parameter:
        json_ref = json_parameter["$ref"]
        return get_ref_data_js(json_ref, scope_domain_name)
    elif "type" in json_parameter:
        json_type = json_parameter["type"]
        return RawTypes.get_js(json_type)
    else:
        raise Exception("Unknown type")


def get_ref_data_js(json_ref, scope_domain_name):
    dot_pos = json_ref.find(".")
    if dot_pos == -1:
        domain_name = scope_domain_name
        type_name = json_ref
    else:
        domain_name = json_ref[:dot_pos]
        type_name = json_ref[dot_pos + 1:]

    return type_map.get(domain_name, type_name).get_raw_type_js()


input_file = open(input_json_filename, "r")
json_string = input_file.read()
json_api = json.loads(json_string)


class Templates:

    def get_this_script_path_(absolute_path):
        absolute_path = os.path.abspath(absolute_path)
        components = []

        def fill_recursive(path_part, depth):
            if depth <= 0 or path_part == '/':
                return
            fill_recursive(os.path.dirname(path_part), depth - 1)
            components.append(os.path.basename(path_part))

        # Typical path is /Source/platform/inspector_protocol/CodeGenerator.py
        # Let's take 4 components from the real path then.
        fill_recursive(absolute_path, 4)

        return "/".join(components)

    file_header_ = ("// File is generated by %s\n\n" % get_this_script_path_(sys.argv[0]) +
                    """// Copyright (c) 2011 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.
""")

    backend_js = string.Template(file_header_ + """

$domainInitializers
""")


type_map = TypeMap(json_api)


class Generator:
    backend_js_domain_initializer_list = []

    @staticmethod
    def go():
        for json_domain in json_api["domains"]:
            domain_name = json_domain["domain"]
            domain_name_lower = domain_name.lower()
            if domain_name_lower == "console":
                continue

            Generator.backend_js_domain_initializer_list.append("// %s.\n" % domain_name)

            if "types" in json_domain:
                for json_type in json_domain["types"]:
                    if "type" in json_type and json_type["type"] == "string" and "enum" in json_type:
                        enum_name = "%s.%s" % (domain_name, json_type["id"])
                        Generator.process_enum(json_type, enum_name)
                    elif json_type["type"] == "object":
                        if "properties" in json_type:
                            for json_property in json_type["properties"]:
                                if "type" in json_property and json_property["type"] == "string" and "enum" in json_property:
                                    enum_name = "%s.%s%s" % (domain_name, json_type["id"], to_title_case(json_property["name"]))
                                    Generator.process_enum(json_property, enum_name)

            if "events" in json_domain:
                for json_event in json_domain["events"]:
                    Generator.process_event(json_event, domain_name)

            if "commands" in json_domain:
                for json_command in json_domain["commands"]:
                    Generator.process_command(json_command, domain_name)

            Generator.backend_js_domain_initializer_list.append("\n")

    @staticmethod
    def process_enum(json_enum, enum_name):
        enum_members = []
        for member in json_enum["enum"]:
            enum_members.append("%s: \"%s\"" % (fix_camel_case(member), member))

        Generator.backend_js_domain_initializer_list.append("Protocol.inspectorBackend.registerEnum(\"%s\", {%s});\n" %
                                                            (enum_name, ", ".join(enum_members)))

    @staticmethod
    def process_event(json_event, domain_name):
        event_name = json_event["name"]

        json_parameters = json_event.get("parameters")

        backend_js_event_param_list = []
        if json_parameters:
            for parameter in json_parameters:
                parameter_name = parameter["name"]
                backend_js_event_param_list.append("\"%s\"" % parameter_name)

        Generator.backend_js_domain_initializer_list.append("Protocol.inspectorBackend.registerEvent(\"%s.%s\", [%s]);\n" %
                                                            (domain_name, event_name, ", ".join(backend_js_event_param_list)))

    @staticmethod
    def process_command(json_command, domain_name):
        json_command_name = json_command["name"]

        js_parameters_text = ""
        if "parameters" in json_command:
            json_params = json_command["parameters"]
            js_param_list = []

            for json_parameter in json_params:
                json_param_name = json_parameter["name"]
                js_bind_type = resolve_param_raw_type_js(json_parameter, domain_name)

                optional = json_parameter.get("optional")

                js_param_text = "{\"name\": \"%s\", \"type\": \"%s\", \"optional\": %s}" % (json_param_name, js_bind_type, (
                    "true" if ("optional" in json_parameter and json_parameter["optional"]) else "false"))

                js_param_list.append(js_param_text)

            js_parameters_text = ", ".join(js_param_list)

        backend_js_reply_param_list = []
        if "returns" in json_command:
            for json_return in json_command["returns"]:
                json_return_name = json_return["name"]
                backend_js_reply_param_list.append("\"%s\"" % json_return_name)

        js_reply_list = "[%s]" % ", ".join(backend_js_reply_param_list)
        if "error" in json_command:
            has_error_data_param = "true"
        else:
            has_error_data_param = "false"

        Generator.backend_js_domain_initializer_list.append(
            "Protocol.inspectorBackend.registerCommand(\"%s.%s\", [%s], %s, %s);\n" %
            (domain_name, json_command_name, js_parameters_text, js_reply_list, has_error_data_param))


Generator.go()

backend_js_file = open(output_js_dirname + "/InspectorBackendCommands.js", "w")

backend_js_file.write(
    Templates.backend_js.substitute(
        None, domainInitializers="".join(Generator.backend_js_domain_initializer_list)))

backend_js_file.close()
