# Copyright 2015 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.

from code import Code
from model import PropertyType

from datetime import datetime

LICENSE = """// Copyright %s 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.
"""

INFO = """// This file was generated by:
//   %s.
"""


class JsUtil(object):
  """A helper class for generating JS Code.
  """
  def GetLicense(self):
    """Returns the license text for JS extern and interface files.
    """
    return (LICENSE % datetime.now().year)

  def GetInfo(self, tool):
    """Returns text describing how the file was generated.
    """
    return (INFO % tool)

  def AppendObjectDefinition(self, c, namespace_name, properties,
                               new_line=True):
    """Given an OrderedDict of properties, returns a Code containing the
       description of an object.
    """
    if not properties: return

    c.Sblock('{', new_line=new_line)
    first = True
    for field, prop in properties.items():
      # Avoid trailing comma.
      # TODO(devlin): This will be unneeded, if/when
      # https://github.com/google/closure-compiler/issues/796 is fixed.
      if not first:
        c.Append(',', new_line=False)
      first = False
      js_type = self._TypeToJsType(namespace_name, prop.type_)
      if prop.optional:
        js_type = (Code().Append('(')
                         .Concat(js_type, new_line=False)
                         .Append('|undefined)', new_line=False))
      c.Append('%s: ' % field, strip_right=False)
      c.Concat(js_type, new_line=False)

    c.Eblock('}')

  def AppendFunctionJsDoc(self, c, namespace_name, function):
    """Appends the documentation for a function as a Code.

    Returns an empty code object if the object has no documentation.
    """
    c.Sblock(line='/**', line_prefix=' * ')

    if function.description:
      c.Comment(function.description, comment_prefix='')

    def append_field(c, tag, js_type, name, optional, description):
      c.Append('@%s {' % tag)
      c.Concat(js_type, new_line=False)
      if optional:
        c.Append('=', new_line=False)
      c.Append('}', new_line=False)
      c.Comment(' %s' % name, comment_prefix='', wrap_indent=4, new_line=False)
      if description:
        c.Comment(' %s' % description, comment_prefix='',
                  wrap_indent=4, new_line=False)

    for param in function.params:
      append_field(c, 'param',
                   self._TypeToJsType(namespace_name, param.type_),
                   param.name, param.optional, param.description)

    if function.callback:
      append_field(c, 'param',
                   self._FunctionToJsFunction(namespace_name,
                                              function.callback),
                   function.callback.name, function.callback.optional,
                   function.callback.description)

    if function.returns:
      append_field(c, 'return',
                   self._TypeToJsType(namespace_name, function.returns),
                   '', False, function.returns.description)

    if function.deprecated:
      c.Append('@deprecated %s' % function.deprecated)

    c.Append(self.GetSeeLink(namespace_name, 'method', function.name))

    c.Eblock(' */')

  def _FunctionToJsFunction(self, namespace_name, function):
    """Converts a model.Function to a JS type (i.e., function([params])...)"""
    c = Code()
    c.Append('function(')
    for i, param in enumerate(function.params):
      c.Concat(self._TypeToJsType(namespace_name, param.type_), new_line=False)
      if i is not len(function.params) - 1:
        c.Append(', ', new_line=False, strip_right=False)
    c.Append('):', new_line=False)

    if function.returns:
      c.Concat(self._TypeToJsType(namespace_name, function.returns),
               new_line=False)
    else:
      c.Append('void', new_line=False)

    return c

  def _TypeToJsType(self, namespace_name, js_type):
    """Converts a model.Type to a JS type (number, Array, etc.)"""
    if js_type.property_type in (PropertyType.INTEGER, PropertyType.DOUBLE):
      return Code().Append('number')
    if js_type.property_type is PropertyType.OBJECT:
      if js_type.properties:
        c = Code()
        self.AppendObjectDefinition(c, namespace_name, js_type.properties)
        return c
      return Code().Append('Object')
    if js_type.property_type is PropertyType.ARRAY:
      return (Code().Append('!Array<').
              Concat(self._TypeToJsType(namespace_name, js_type.item_type),
                     new_line=False).
           Append('>', new_line=False))
    if js_type.property_type is PropertyType.REF:
      ref_type = '!chrome.%s.%s' % (namespace_name, js_type.ref_type)
      return Code().Append(ref_type)
    if js_type.property_type is PropertyType.CHOICES:
      c = Code()
      c.Append('(')
      for i, choice in enumerate(js_type.choices):
        c.Concat(self._TypeToJsType(namespace_name, choice), new_line=False)
        if i is not len(js_type.choices) - 1:
          c.Append('|', new_line=False)
      c.Append(')', new_line=False)
      return c
    if js_type.property_type is PropertyType.FUNCTION:
      return self._FunctionToJsFunction(namespace_name, js_type.function)
    if js_type.property_type is PropertyType.BINARY:
      return Code().Append('ArrayBuffer')
    if js_type.property_type is PropertyType.ANY:
      return Code().Append('*')
    if js_type.property_type.is_fundamental:
      return Code().Append(js_type.property_type.name)
    return Code().Append('?') # TODO(tbreisacher): Make this more specific.

  def GetSeeLink(self, namespace_name, object_type, object_name):
    """Returns a @see link for a given API 'object' (type, method, or event).
    """

    # NOTE(devlin): This is kind of a hack. Some APIs will be hosted on
    # developer.chrome.com/apps/ instead of /extensions/, and some APIs have
    # '.'s in them (like app.window), which should resolve to 'app_window'.
    # Luckily, the doc server has excellent url resolution, and knows exactly
    # what we mean. This saves us from needing any complicated logic here.
    return ('@see https://developer.chrome.com/extensions/%s#%s-%s' %
                (namespace_name, object_type, object_name))
