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

"""Code shared by the various language-specific code generators."""

from functools import partial
import os.path
import re

import module as mojom
import mojom.fileutil as fileutil
import pack

def ExpectedArraySize(kind):
  if mojom.IsArrayKind(kind):
    return kind.length
  return None

def StudlyCapsToCamel(studly):
  return studly[0].lower() + studly[1:]

def UnderToCamel(under):
  """Converts underscore_separated strings to CamelCase strings."""
  return ''.join(word.capitalize() for word in under.split('_'))

def WriteFile(contents, full_path):
  # Make sure the containing directory exists.
  full_dir = os.path.dirname(full_path)
  fileutil.EnsureDirectoryExists(full_dir)

  # Dump the data to disk.
  with open(full_path, "w+") as f:
    f.write(contents)

class Generator(object):
  # Pass |output_dir| to emit files to disk. Omit |output_dir| to echo all
  # files to stdout.
  def __init__(self, module, output_dir=None, typemap=None, variant=None,
               bytecode_path=None, for_blink=False, use_once_callback=False,
               use_new_js_bindings=False, export_attribute=None,
               export_header=None, generate_non_variant_code=False):
    self.module = module
    self.output_dir = output_dir
    self.typemap = typemap or {}
    self.variant = variant
    self.bytecode_path = bytecode_path
    self.for_blink = for_blink
    self.use_once_callback = use_once_callback
    self.use_new_js_bindings = use_new_js_bindings
    self.export_attribute = export_attribute
    self.export_header = export_header
    self.generate_non_variant_code = generate_non_variant_code

  def GetStructsFromMethods(self):
    result = []
    for interface in self.module.interfaces:
      for method in interface.methods:
        result.append(self._GetStructFromMethod(method))
        if method.response_parameters != None:
          result.append(self._GetResponseStructFromMethod(method))
    return result

  def GetStructs(self):
    return map(partial(self._AddStructComputedData, True), self.module.structs)

  def GetUnions(self):
    return map(self._AddUnionComputedData, self.module.unions)

  def GetInterfaces(self):
    return map(self._AddInterfaceComputedData, self.module.interfaces)

  # Prepend the filename with a directory that matches the directory of the
  # original .mojom file, relative to the import root.
  def MatchMojomFilePath(self, filename):
    return os.path.join(os.path.dirname(self.module.path), filename)

  def Write(self, contents, filename):
    if self.output_dir is None:
      print contents
      return
    full_path = os.path.join(self.output_dir, filename)
    WriteFile(contents, full_path)

  def GenerateFiles(self, args):
    raise NotImplementedError("Subclasses must override/implement this method")

  def GetJinjaParameters(self):
    """Returns default constructor parameters for the jinja environment."""
    return {}

  def GetGlobals(self):
    """Returns global mappings for the template generation."""
    return {}

  def _AddStructComputedData(self, exported, struct):
    """Adds computed data to the given struct. The data is computed once and
    used repeatedly in the generation process."""
    struct.packed = pack.PackedStruct(struct)
    struct.bytes = pack.GetByteLayout(struct.packed)
    struct.versions = pack.GetVersionInfo(struct.packed)
    struct.exported = exported
    return struct

  def _AddUnionComputedData(self, union):
    """Adds computed data to the given union. The data is computed once and
    used repeatedly in the generation process."""
    ordinal = 0
    for field in union.fields:
      if field.ordinal is not None:
        ordinal = field.ordinal
      field.ordinal = ordinal
      ordinal += 1
    return union

  def _AddInterfaceComputedData(self, interface):
    """Adds computed data to the given interface. The data is computed once and
    used repeatedly in the generation process."""
    interface.version = 0
    for method in interface.methods:
      if method.min_version is not None:
        interface.version = max(interface.version, method.min_version)

      method.param_struct = self._GetStructFromMethod(method)
      interface.version = max(interface.version,
                              method.param_struct.versions[-1].version)

      if method.response_parameters is not None:
        method.response_param_struct = self._GetResponseStructFromMethod(method)
        interface.version = max(
            interface.version,
            method.response_param_struct.versions[-1].version)
      else:
        method.response_param_struct = None
    return interface

  def _GetStructFromMethod(self, method):
    """Converts a method's parameters into the fields of a struct."""
    params_class = "%s_%s_Params" % (method.interface.name, method.name)
    struct = mojom.Struct(params_class, module=method.interface.module)
    for param in method.parameters:
      struct.AddField(param.name, param.kind, param.ordinal,
                      attributes=param.attributes)
    return self._AddStructComputedData(False, struct)

  def _GetResponseStructFromMethod(self, method):
    """Converts a method's response_parameters into the fields of a struct."""
    params_class = "%s_%s_ResponseParams" % (method.interface.name, method.name)
    struct = mojom.Struct(params_class, module=method.interface.module)
    for param in method.response_parameters:
      struct.AddField(param.name, param.kind, param.ordinal,
                      attributes=param.attributes)
    return self._AddStructComputedData(False, struct)
