from __future__ import absolute_import

'''// Generated by the protocol buffer compiler.  DO NOT EDIT!\n
// source: $file_name$\n", "file_name"
/**
*   @fileoverview Generated Protocol Buffer code for file %(filename)s.
*/'''

TMPL_PROVIDE = '''goog.provide('%(name)s');'''

TMPL_REQUIRE = '''goog.require('goog.proto2.Message');'''

TMPL_MESSAGE_CONST = '''/** Message %(name)s.
*   @constructor
*   @extends {goog.proto2.Message}
*/
%(name)s = function() {
    goog.base(this);
}
goog.inherits( %(name)s, goog.proto2.Message);

'''

TMPL_META = '''
  goog.proto2.Message.set$Metadata(MessageType, {
    0: {
      name: 'test_message',
      fullName: 'this.is.a.test_message'
    },
    10: {
      name: 'test',
      fieldType: 7,
      type: Number
    }
  });

'''
import json
import pyprotobuf.nodes as nodes
from pyprotobuf.codegenerator import CodeGenerator        


GOOG_PROTO2_TYPE_MAP = {
    'bool':'goog.proto2.Message.FieldType.BOOLEAN',
    'string': 'goog.proto2.Message.FieldType.STRING',
    'int64': 'goog.proto2.Message.FieldType.INT64',        
    'int32': 'goog.proto2.Message.FieldType.INT32',
    'uint64': 'goog.proto2.Message.FieldType.UINT64', 
    'uint32': 'goog.proto2.Message.FieldType.UINT32',
    'sint64': 'goog.proto2.Message.FieldType.SINT64', 
    'sint32': 'goog.proto2.Message.FieldType.SINT32',
    'fixed64': 'goog.proto2.Message.FieldType.FIXED64', 
    'fixed32': 'goog.proto2.Message.FieldType.FIXED32',
    'sfixed64': 'goog.proto2.Message.FieldType.SFIXED64',   
    'sfixed32': 'goog.proto2.Message.FieldType.SFIXED32',    
    'double': 'goog.proto2.Message.FieldType.DOUBLE',    
    'float': 'goog.proto2.Message.FieldType.FLOAT', 
    'bytes': 'goog.proto2.Message.FieldType.BYTES',
    'enum': 'goog.proto2.Message.FieldType.ENUM',
    'message': 'goog.proto2.Message.FieldType.MESSAGE'
}

JS_TYPE_MAP = {
    'bool':'boolean',
    'bytes': 'string',
    'double': 'number',    
    'fixed32': 'number',
    'fixed64': 'string', 
    'float': 'number', 
    'int32': 'number',
    'int64': 'string',        
    'sfixed32': 'number',    
    'sfixed64': 'string',   
    'sint32': 'number',
    'sint64': 'string', 
    'string': 'string',
    'uint32': 'number',
    'uint64': 'string', 
}

'''
"/**\n"
" * Enumeration $name$.\n"
" * @enum {number}\n"
" */\n",
$name$ = {
'''
class ClosureLib(CodeGenerator):
    
    comment = '//'
    prefix = ''
    
    def generate_file(self, protonode):
        self.output.write(TMPL_REQUIRE + '\n\n')
        self.visit(protonode)
        
        return self.output.to_string()
    
    def visit_MessageNode(self, node):
        # loop over fields
        fields = filter(lambda x: isinstance(x, nodes.FieldDescriptorNode), node.children)
        fields = sorted(fields, key=lambda x: x.number)
        all_field_meta = {}
        messagemeta = {'name': node.get_full_name(), 'prefix' : self.prefix}
        
        self.output.write(TMPL_MESSAGE_CONST % messagemeta)
        self.output.write('goog.proto2.Message.set$$Metadata(%(prefix)s%(name)s, {\n'% messagemeta)
        lines = []
        for field in fields:
            field_number = field.number
            field_meta = all_field_meta[field_number] = {}
            
            jsfieldtype = GOOG_PROTO2_TYPE_MAP.get(field.type)
            jstype = str(field.type)
            if isinstance(field.type, nodes.MessageNode):
                jstype = '{0}{1}'.format(self.prefix, field.get_full_typename())
                jsfieldtype = GOOG_PROTO2_TYPE_MAP.get('message')
            elif isinstance(field.type, nodes.EnumNode):
                jstype = field.get_full_typename()
                jsfieldtype = GOOG_PROTO2_TYPE_MAP.get('enum')
            else:
                jstype = JS_TYPE_MAP.get(field.type, None)
            
            line = ['%s : { ' % field.number]
            field_meta['name'] = field.name
            field_meta['fieldType'] = jsfieldtype
            field_meta['type'] = jstype
            field_meta['prefix'] = self.prefix
            line.append("'name':'%(name)s', 'fieldType': %(fieldType)s, 'type': %(type)s" % field_meta)
            
            if field.label == "repeated":
                field_meta['repeated'] = True
                line.append(", 'repeated': true")
            if hasattr(field, 'default'):
                field_meta['defaultValue'] = json.dumps(field.default)
                line.append(", 'defaultValue': %(defaultValue)s" % field_meta)
            line.append("}")
            lines.append(''.join(line))
          
        self.output.write(',\n'.join(lines))  
        
        self.output.write('\n});')

        self.output.write('\n\n')
        
        
    def visit_FieldDescriptorNode(self, node):
        pass
    
    def visit_OptionNode(self, node):
        if node.name == 'javascript_package':
            self.prefix = node.value.strip('"') + '.'    
 
__generator__ = ClosureLib
