#!/usr/bin/env ruby

# A script to automatically generate SQL files from an interface definition.
# To be called like this: sql-template-renderer interface.yaml sql-template.erb

require 'yaml'
require 'erb'

class SqlTemplateRenderer

  DATASERVICES_CLIENT_SCHEMA = 'cdb_dataservices_client'
  DATASERVICES_SERVER_SCHEMA = 'cdb_dataservices_server'

  def initialize(template_file, function_signature)
    @function_signature = function_signature
    @template = File.read(template_file)
  end

  def render
    ERB.new(@template, _save_level=nil, _trim_mode='-').result(binding)
  end

  def name
    @function_signature['name']
  end

  def return_type
    @function_signature['return_type']
  end

  def requires_permission
    @function_signature['requires_permission']
  end

  def permission_name
    @function_signature['permission_name']
  end

  def permission_error
    @function_signature['permission_error']
  end

  def multi_field
    @function_signature['multi_field']
  end

  def multi_row
    @function_signature['multi_row']
  end

  def user_config_key
    @function_signature['user_config_key']
  end

  def geocoder_config_key
    @function_signature['geocoder_config_key']
  end

  def parameters_info(with_user_org)
    parameters = []
    if with_user_org
      parameters << { 'name' => 'username', 'type' => 'text' }
      parameters << { 'name' => 'orgname',  'type' => 'text' }
    end
    parameters + @function_signature['params'].reject(&:empty?)
  end

  def user_org_declaration()
    "username text;\n  orgname text;" unless superuser_function?
  end

  def params(with_user_org = superuser_function?)
    parameters_info(with_user_org).map { |p| p['name'].to_s }
  end

  def params_with_type(with_user_org = superuser_function?)
    parameters_info(with_user_org).map { |p| "#{p['name']} #{p['type']}" }
  end

  def params_with_type_and_default(with_user_org = superuser_function?)
    parameters = parameters_info(with_user_org).map do |p|
      if not p['default'].nil?
        "#{p['name']} #{p['type']} DEFAULT #{p['default']}"
      else
        "#{p['name']} #{p['type']}"
      end
    end
    return parameters
  end

  def superuser_function?
    !!@function_signature['superuser']
  end

  def void_return_type?
    return_type.downcase == 'void'
  end

  def return_declaration
     "ret #{return_type};" unless void_return_type? || multi_row
  end

  def return_statement(&block)
    if block
      erb_out = block.binding.eval('_erbout')

      if multi_row
        erb_out << 'RETURN QUERY SELECT * FROM '
      elsif multi_field
        erb_out << 'SELECT * FROM '
      elsif void_return_type?
        erb_out << 'PERFORM '
      else
        erb_out << 'SELECT '
      end
      yield
      if multi_row || void_return_type?
        erb_out << ';'
      else
        erb_out << ' INTO ret;'
      end
      if !multi_row && !void_return_type?
        erb_out << ' RETURN ret;'
      end
    else
      if !multi_row && !void_return_type?
        ' RETURN ret;'
      end
    end
  end


end


if ARGV.length != 2 then
  puts "Usage: sql-template-renderer <interface.yaml> <template.erb>"
  exit
end

interface_source_file = ARGV[0]
template_file = ARGV[1]


functions = YAML.load(File.open(interface_source_file))

functions.each do |f|
  puts SqlTemplateRenderer.new(template_file, f).render
end
