#!/usr/bin/env python
#
# Copyright 2016 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

"""protoc plugin to convert a protobuf schema to a yang schema

   - basic support for message, fields. enumeration, service, method

   - yang semantic rules needs to be implemented

   - to run this plugin :

   $ python -m grpc.tools.protoc -I.
   --plugin=protoc-gen-custom=./proto2yang.py --custom_out=. <proto file>.proto

   - the above will produce a <proto file>.yang file formatted for yang

   - two examples of proto that can be used in the same directory are
   yang.proto and addressbook.proto

"""

import sys

from jinja2 import Template
from google.protobuf.compiler import plugin_pb2 as plugin
from descriptor_parser import DescriptorParser

from google.protobuf.descriptor import FieldDescriptor

template_yang = Template("""
module {{ module.name }} {

    namespace "https://gerrit.opencord.org/voltha/{{ module.package }}";
    yang-version 1.1;

    prefix "voltha";

    revision 2016-11-15 {{ module.revision }} {
    {% if module.description %}
        /* {{ message.description }} */
    {% else %}
        description "Initial revision.";
    {% endif %}
    }

    {% for enum in module.enums %}
    {% if enum.description %}
    /* {{ enum.description }} */
    {% endif %}
    typedef {{ enum.name }} {
        type enumeration {
        {% for v in enum.value %}
        {% if v.description %}
            enum {{ v.name }} {
                description "{{ v.description }}";
            }
        {% else %}
            enum {{ v.name }} ;
        {% endif %}
        {% endfor %}
        }
    }
    {% endfor %}

    {% for message in module.messages recursive %}
    {% if message.name in module.referenced_messages %}
    grouping {{ message.name }} {
    {% else %}
    container {{ message.name }} {
    {% endif %}
        {% if message.description %}
        /* {{ message.description }} */
        {% endif %}
        {% for field in message.fields %}
        {% if field.type_ref %}
        {% if field.description %}
        /* {{ field.description }} */
        {% endif %}
        {% for dict_item in module.referred_messages_with_keys %}
                {% if dict_item.name == field.type %}
        list {{ field.name }} {
            key "{{ dict_item.key }}";
            {% if not field.repeated %}
            max-elements 1;
            {% endif %}
            uses {{ field.type }};
        }
                {% endif %}
        {% endfor %}
        {% elif field.repeated %}
        list {{ field.name }} {
            key "{{ field.name }}";
            leaf {{ field.name }} {
                {% if field.type == "decimal64" %}
                type {{ field.type }} {
                   fraction-digits 5;
                }
                {% else %}
                type {{ field.type }} ;
                {% endif %}
                {% if field.description %}
                description
                    "{{ field.description }}" ;
                {% endif %}
            }
        }
        {% else %}
        leaf {{ field.name }} {
            {% if field.type == "decimal64" %}
            type {{ field.type }} {
               fraction-digits 5;
            }
            {% else %}
            type {{ field.type }} ;
            {% endif %}
            {% if field.description %}
            description
                "{{ field.description }}" ;
            {% endif %}
        }
        {% endif %}

        {% endfor %}
        {% for enum_type in message.enums %}
        {% if enum_type.description %}
        /* {{ enum_type.description }} */
        {% endif %}
        typedef {{ enum_type.name }} {
            type enumeration {
            {% for v in enum_type.value %}
            {% if v.description %}
                enum {{ v.name }} {
                    description "{{ v.description }}";
                }
            {% else %}
                enum {{ v.name }} ;
            {% endif %}
            {% endfor %}
            }
        }

        {% endfor %}
    {% if message.messages %}
    {{ loop (message.messages)|indent(4, false) }}
    {% endif %}
    }

    {% endfor %}
    {% for service in module.services %}
    {% if service.description %}
    /*  {{ service.description }}" */
    {% endif %}
    {% for method in service.methods %}
    {% if method.description %}
    /* {{ method.description }} */
    {% endif %}
    rpc {{ service.service }}-{{ method.method }} {
        {% if method.input %}
        input {
            {% if method.input_ref %}
            uses {{ method.input }} ;
            {% else %}
            leaf {{ method.input }} {
                type {{ method.input }} ;
            }
            {% endif %}
        }
        {% endif %}
        {% if method.output %}
        output {
            {% if method.output_ref %}
            uses {{ method.output }} ;
            {% else %}
            leaf {{ method.output }} {
                type {{ method.output }} ;
            }
            {% endif %}
        }
        {% endif %}
    }

    {% endfor %}

    {% endfor %}
}
""", trim_blocks=True, lstrip_blocks=True)


def traverse_messages(message_types, prefix, referenced_messages):
    messages = []
    for message_type in message_types:
        assert message_type['_type'] == 'google.protobuf.DescriptorProto'

        # full_name = prefix + '-' + message_type['name']
        full_name = message_type['name']

        # parse the fields
        fields = traverse_fields(message_type.get('field', []), full_name,
                                 referenced_messages)

        # parse the enums
        enums = traverse_enums(message_type.get('enum_type', []), full_name)

        # parse nested messages
        nested = message_type.get('nested_type', [])
        nested_messages = traverse_messages(nested, full_name,
                                            referenced_messages)
        messages.append(
            {
                'name': full_name,
                'fields': fields,
                'enums': enums,
                # 'extensions': extensions,
                'messages': nested_messages,
                'description': remove_unsupported_characters(
                    message_type.get('_description', '')),
                # 'extension_ranges': extension_ranges,
                # 'oneof': oneof
            }
        )
    return messages


def traverse_fields(fields_desc, prefix, referenced_messages):
    fields = []
    for field in fields_desc:
        assert field['_type'] == 'google.protobuf.FieldDescriptorProto'
        yang_base_type = is_base_type(field['type'])
        _type = get_yang_type(field)
        if not yang_base_type:
            referenced_messages.append(_type)

        fields.append(
            {
                # 'name': prefix + '-' + field.get('name', ''),
                'name': field.get('name', ''),
                'label': field.get('label', ''),
                'repeated': field['label'] == FieldDescriptor.LABEL_REPEATED,
                'number': field.get('number', ''),
                'options': field.get('options', ''),
                'type_name': field.get('type_name', ''),
                'type': _type,
                'type_ref': not yang_base_type,
                'description': remove_unsupported_characters(field.get(
                    '_description', ''))
            }
        )
    return fields


def traverse_enums(enums_desc, prefix):
    enums = []
    for enum in enums_desc:
        assert enum['_type'] == 'google.protobuf.EnumDescriptorProto'
        # full_name = prefix + '-' + enum.get('name', '')
        full_name = enum.get('name', '')
        enums.append(
            {
                'name': full_name,
                'value': enum.get('value', ''),
                'description': remove_unsupported_characters(enum.get(
                    '_description', ''))
            }
        )
    return enums


def traverse_services(service_desc, referenced_messages):
    services = []
    for service in service_desc:
        methods = []
        for method in service.get('method', []):
            assert method['_type'] == 'google.protobuf.MethodDescriptorProto'

            input_name = method.get('input_type')
            input_ref = False
            if not is_base_type(input_name):
                input_name = remove_first_character_if_match(input_name, '.')
                # input_name = input_name.replace(".", "-")
                input_name = input_name.split('.')[-1]
                referenced_messages.append(input_name)
                input_ref = True

            output_name = method.get('output_type')
            output_ref = False
            if not is_base_type(output_name):
                output_name = remove_first_character_if_match(output_name, '.')
                # output_name = output_name.replace(".", "-")
                output_name = output_name.split('.')[-1]
                referenced_messages.append(output_name)
                output_ref = True

            methods.append(
                {
                    'method': method.get('name', ''),
                    'input': input_name,
                    'input_ref': input_ref,
                    'output': output_name,
                    'output_ref': output_ref,
                    'description': remove_unsupported_characters(method.get(
                        '_description', '')),
                    'server_streaming': method.get('server_streaming',
                                                   False) == True
                }
            )
        services.append(
            {
                'service': service.get('name', ''),
                'methods': methods,
                'description': remove_unsupported_characters(service.get(
                    '_description', '')),
            }
        )
    return services


def rchop(thestring, ending):
    if thestring.endswith(ending):
        return thestring[:-len(ending)]
    return thestring


def traverse_desc(descriptor):
    referenced_messages = []
    name = rchop(descriptor.get('name', ''), '.proto')
    package = descriptor.get('package', '')
    description = descriptor.get('_description', '')
    messages = traverse_messages(descriptor.get('message_type', []),
                                 package, referenced_messages)
    enums = traverse_enums(descriptor.get('enum_type', []), package)
    services = traverse_services(descriptor.get('service', []),
                                 referenced_messages)
    # extensions = _traverse_extensions(descriptors)
    # options = _traverse_options(descriptors)
    set_messages_keys(messages)
    unique_referred_messages_with_keys = []
    for message_name in list(set(referenced_messages)):
        unique_referred_messages_with_keys.append(
            {
                'name': message_name,
                'key': get_message_key(message_name, messages)
            }
        )

    data = {
        'name': name,
        'package': package,
        'description': description,
        'messages': messages,
        'enums': enums,
        'services': services,
        'referenced_messages': list(set(referenced_messages)),
        # TODO:  simplify for easier jinja2 template use
        'referred_messages_with_keys': unique_referred_messages_with_keys,
        # 'extensions': extensions,
        # 'options': options
    }
    return data


def set_messages_keys(messages):
    for message in messages:
        message['key'] = _get_message_key(message)
        if message['messages']:
            set_messages_keys(message['messages'])


def _get_message_key(message):
    # assume key is first yang base type field
    for field in message['fields']:
        if not field['type_ref']:
            return field['name']
    # no key yet - search nested messaged
    if message['messages']:
        return get_message_key(message['messages'])
    else:
        return None


def get_message_key(message_name, messages):
    for message in messages:
        if message_name == message['name']:
            return message['key']
        if message['messages']:
            return get_message_key(message_name, message['messages'])
    return None


def generate_code(request, response):
    assert isinstance(request, plugin.CodeGeneratorRequest)

    parser = DescriptorParser()

    # idx = 1
    for proto_file in request.proto_file:
        native_data = parser.parse_file_descriptor(proto_file,
                                                   type_tag_name='_type',
                                                   fold_comments=True)

        # print native_data
        yang_data = traverse_desc(native_data)

        f = response.file.add()
        # TODO: We should have a separate file for each output. There is an
        # issue reusing the same filename with an incremental suffix.  Using
        # a different file name works but not the actual proto file name
        f.name = proto_file.name.replace('.proto', '.yang')
        # f.name = '{}_{}{}'.format(_rchop(proto_file.name, '.proto'), idx,
        #                            '.yang')
        # idx += 1
        f.content = template_yang.render(module=yang_data)


def get_yang_type(field):
    type = field['type']
    if type in YANG_TYPE_MAP.keys():
        _type, _ = YANG_TYPE_MAP[type]
        if _type in ['enumeration', 'message', 'group']:
            return field['type_name'].split('.')[-1]
            # return remove_first_character_if_match(field['type_name'],
            #                                        '.').replace('.', '-')
        else:
            return _type
    else:
        return type


def is_base_type(type):
    # check numeric value of the type first
    if type in YANG_TYPE_MAP.keys():
        _type, _ = YANG_TYPE_MAP[type]
        return _type not in ['message', 'group']
    else:
        # proto name of the type
        result = [_format for (_, _format) in YANG_TYPE_MAP.values() if
                  _format == type and _format not in ['message', 'group']]
        return len(result) > 0


def remove_unsupported_characters(text):
    unsupported_characters = ["{", "}", "[", "]", "\"", "\\", "*", "/"]
    return ''.join([i if i not in unsupported_characters else ' ' for i in
                    text])


def remove_first_character_if_match(str, char):
    if str.startswith(char):
        return str[1:]
    return str


YANG_TYPE_MAP = {
    FieldDescriptor.TYPE_BOOL: ('boolean', 'boolean'),
    FieldDescriptor.TYPE_BYTES: ('binary', 'byte'),
    FieldDescriptor.TYPE_DOUBLE: ('decimal64', 'double'),
    FieldDescriptor.TYPE_ENUM: ('enumeration', 'enum'),
    FieldDescriptor.TYPE_FIXED32: ('int32', 'int64'),
    FieldDescriptor.TYPE_FIXED64: ('int64', 'uint64'),
    FieldDescriptor.TYPE_FLOAT: ('decimal64', 'float'),
    FieldDescriptor.TYPE_INT32: ('int32', 'int32'),
    FieldDescriptor.TYPE_INT64: ('int64', 'int64'),
    FieldDescriptor.TYPE_SFIXED32: ('int32', 'int32'),
    FieldDescriptor.TYPE_SFIXED64: ('int64', 'int64'),
    FieldDescriptor.TYPE_STRING: ('string', 'string'),
    FieldDescriptor.TYPE_SINT32: ('int32', 'int32'),
    FieldDescriptor.TYPE_SINT64: ('int64', 'int64'),
    FieldDescriptor.TYPE_UINT32: ('uint32', 'int64'),
    FieldDescriptor.TYPE_UINT64: ('uint64', 'uint64'),
    FieldDescriptor.TYPE_MESSAGE: ('message', 'message'),
    FieldDescriptor.TYPE_GROUP: ('group', 'group')
}

if __name__ == '__main__':
    # Read request message from stdin
    data = sys.stdin.read()

    # Parse request
    request = plugin.CodeGeneratorRequest()
    request.ParseFromString(data)

    # Create response
    response = plugin.CodeGeneratorResponse()

    # Generate code
    generate_code(request, response)

    # Serialise response message
    output = response.SerializeToString()

    # Write to stdout
    sys.stdout.write(output)
    # print is_base_type(9)
