#! /usr/bin/python3

import os

def strip_arg(s):
  s = s.strip()
  if s and s[0] == '[':
    s = s[1:len(s)-1]
  return s.strip()

def parse_func(s, start=0):
  pos = s.find('(', start)
  func = s[start:pos].strip()

  args = []
  n_brackets=0
  n_parenthesis=1
  start = pos = pos + 1
  while n_parenthesis > 0:
    if s[pos] == '[':
      n_brackets += 1
    elif s[pos] == ']':
      n_brackets -= 1
    elif n_brackets == 0 and s[pos] == '(':
      n_parenthesis += 1
    elif n_brackets == 0 and s[pos] == ')':
      n_parenthesis -= 1
    elif n_brackets == 0 and n_parenthesis == 1 and s[pos] == ',':
      args.append(strip_arg(s[start:pos]))
      start = pos + 1
    pos += 1

  args.append(strip_arg(s[start:pos-1]))

  return func, args, pos

def format_description(desc):
  return desc.replace("'", "\\'")

def gen_user_option(args):
  if args[1].startswith('AS_HELP_STRING') or \
     args[1].startswith('AC_HELP_STRING'):
    help_args = parse_func(args[1])[1]
  elif args[1].startswith('--'):
    p = args[1].find(' ')
    help_args = [args[1][:p].strip(), args[1][p:].strip()]
  else:
    help_args = ['', args[1]]

  type_str = ''
  value_str = ''
  choices = []
  equal_pos = help_args[0].find('=')
  if equal_pos > 0:
    val = help_args[0][equal_pos+1:]
    if val.startswith('@<:@'):
      choices = val[4:val.find('@', 5)].split('/')
    elif val.find('|') > 0:
      choices = val.split('|')

    if choices:
      type_str = "'combo'"
      value_str = "''"
      for c in choices:
        if (len(args) >= 4 and args[3].find(c) > 0) or help_args[1].find(c) > 0:
          value_str = "'{}'".format(c)
          break
    else:
      type_str = "'string'"
      value_str = "''"
  else:
    type_str = "'boolean'"
    value_str = "true" if help_args[0].startswith('--disable') else "false"

  name = args[0].replace('-','_').lower()
  description = format_description(help_args[1])

  output = "option('{}',\n".format(name)
  output += "       type : {},\n".format(type_str)
  if choices:
    output += "       choices : {},\n".format(str(choices))
  output += "       value : {},\n".format(value_str)
  output += "       description : '{}')\n\n".format(description)

  return output

def gen_feature_option(args):
  name = args[0].replace('-','_').lower()
  value = 'false' if len(args) >= 5 and args[4] == 'disabled' else 'true'
  description = args[1]
  if args[2]:
    description += ' : ' + args[2]
  description = format_description(description)

  output = "# GStreamer feature\n"
  output += "option('{}',\n".format(name)
  output += "       type : 'boolean',\n"
  output += "       value : '{}',\n".format(value)
  output += "       description : '{}')\n\n".format(description)

  return output

def gen_plugin_option(args):
  name = args[0].replace('-','_').lower()
  description = format_description(args[0])

  output = "# GStreamer plugin\n"
  output += "option('{}',\n".format(name)
  output += "       type : 'boolean',\n"
  output += "       value : 'true',\n"
  output += "       description : 'build dependency-less {} plugin')\n\n".format(description)

  return output

def gen_subsystem_option(args):
  name = args[0].replace('-','_').lower()
  description = format_description(args[1])

  output = "# GStreamer subsystem\n"
  output += "option('{}',\n".format(name)
  output += "       type : 'boolean',\n"
  output += "       value : 'true',\n"
  output += "       description : '{}')\n\n".format(description)

  return output

def find_next_func(s, start):
  result = -1
  for func in ['AC_ARG_ENABLE', 'AC_ARG_WITH', 'AC_CONFIG_MACRO_DIR',
               'AG_GST_CHECK_FEATURE', 'AG_GST_CHECK_PLUGIN',
               'AG_GST_CHECK_SUBSYSTEM_DISABLE']:
    pos = s.find(func, start)
    if pos < 0:
      continue
    if result < 0 or pos < result:
      result = pos
  return result

def parse_file(filename):
  content = ''
  with open(filename, 'r') as f:
    for line in f:
      if not line.startswith('dnl'):
        content += line

  m4dir = None
  output = ''
  next_pos = 0
  while True:
    start = find_next_func(content, next_pos)
    if start < 0:
      break

    func, args, next_pos = parse_func(content, start)

    if func == 'AC_CONFIG_MACRO_DIR':
      m4dir = args[0]
    elif func in ['AC_ARG_ENABLE', 'AC_ARG_WITH']:
      output += gen_user_option(args)
    elif func == 'AG_GST_CHECK_FEATURE':
      output += gen_feature_option(args)
    elif func == 'AG_GST_CHECK_PLUGIN':
      output += gen_plugin_option(args)
    elif func == 'AG_GST_CHECK_SUBSYSTEM_DISABLE':
      output += gen_subsystem_option(args)

  if output:
    output = '# {}\n\n'.format(filename) + output

  return output, m4dir

def parse_dir(path):
  output = ''
  for f in os.listdir(path):
    filename = os.path.join(path, f)
    output += parse_file(filename)[0]

  return output

if __name__ == "__main__":
  output, m4dir = parse_file('configure.ac')
  if m4dir:
    output += parse_dir(m4dir)
  else:
    output += parse_dir('m4')
    output += parse_dir('common/m4')

  print(output)

