# Copyright (c) 2015, Facebook, Inc.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree. An additional grant
# of patent rights can be found in the PATENTS file in the same directory.

from casing import snake

from license import C_LICENSE_COMMENT

def struct_name(type):
  return 'GraphQLAst' + type


def return_type(type):
  if type == 'OperationKind' or type == 'string':
    return 'const char *'

  if type == 'boolean':
    return 'int'

  return 'const struct %s *' % struct_name(type)


def field_prototype(owning_type, type, name, nullable, plural):
  st_name = struct_name(owning_type)
  if plural:
    return 'int %s_get_%s_size(const struct %s *node)' % (
      st_name, snake(name), st_name)
  else:
    ret_type = return_type(type)
    return '%s %s_get_%s(const struct %s *node)' % (
      ret_type, st_name, snake(name), st_name)


class Printer(object):
  '''Printer for the pure C interface to the AST.

  Merely a set of wrappers around the C++ interface; makes it possible
  to use the AST from C code and simplifies the task of writing
  bindings for other langugages.

  The mapping is as follows:

  - For each concrete type, you get an opaque C struct type,
  accessible only by pointer.

  - For each singular field of a concrete type, you get an accessor
  function, returning said field in the obvious way.

  - For each plural field of a concrete type, you get an accessor
  function telling you its size. For access to elements of a plural
  field, you can use the visitor API.

  - For each union type, you get nothing specific (REVIEW), but you
    can use the visitor API to work around this entirely.

  '''

  def __init__(self):
    self._current_type = None

  def start_file(self):
    print C_LICENSE_COMMENT + '''/** @generated */

#pragma once

#ifdef __cplusplus
extern "C" {
#endif

'''

  def end_file(self):
    print '''

#ifdef __cplusplus
}
#endif
'''

  def start_type(self, name):
    # Forward declarations for AST nodes.
    st_name = struct_name(name)
    print 'struct ' + st_name + ';'
    self._current_type = name

  def field(self, type, name, nullable, plural):
    print field_prototype(self._current_type, type, name, nullable, plural) + ';'

  def end_type(self, name):
    print

  def start_union(self, name):
    print 'struct ' + struct_name(name) + ';'

  def union_option(self, option):
    pass

  def end_union(self, name):
    print
