# 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 AppendTypeJsDoc(self, c, namespace_name, js_type, optional):
    """Appends the documentation for a type as a Code.
    """
    c.Append('@type {')
    if optional:
      c.Append('(', new_line=False)
      c.Concat(self._TypeToJsType(namespace_name, js_type), new_line=False)
      c.Append('|undefined)', new_line=False)
    else:
      c.Concat(self._TypeToJsType(namespace_name, js_type), new_line=False)
    c.Append('}', new_line=False)

  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):
      t = self._TypeToJsType(namespace_name, param.type_)
      if param.optional:
        c.Append('(', new_line=False)
        c.Concat(t, new_line=False)
        c.Append('|undefined)', new_line=False)
      else:
        c.Concat(t, 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))
