#!/usr/bin/perl -w

# example:
# 	/* TYPEINFO: boolean (symbol, symbol, any) */
#	YCPValue ChangeWidget ( const YCPSymbol & widget_id, const YCPSymbol & property, const YCPValue & /*nil*/ new_value );


my $header_file = shift;
my $call_file = shift;
my $register_file = shift;

if ( ! defined $header_file || ! defined $call_file ||
    ! defined $register_file )
{
    die "Required parameters: <header-file> <call-file> <register-file>";
}

use strict;
use integer;

use Data::Dumper;

my @exports = ();

open ( HEADER, $header_file ) 
	or die "Cannot open input header file";

while (my $line = <HEADER>)
{
	chomp ($line);
	if ($line =~ /\/\*\s*TYPEINFO:\s*(.*?)\s*\*\//)
	{
		# get C++ declaration
		my $typeinfo = $1;
		$line = <HEADER>;
		chomp ($line);
		# get the parts of the declaration
		$line =~ /\s*(YCP\w+)\s+(\w+)\s*\(([^\)]*)\)/;
		my $func_returntype = $1 || "";
		my $func_name = $2 || "";
		my $func_params = $3 || "";

		my %data = ( "raw" => $line,
			"signature" => $typeinfo,
                        "name" => $func_name,
                        "returntype" => $func_returntype,
                        "params" => $func_params,
                );

		# store the data
		push ( @exports, \%data );
	}
}

open ( CALL, "> $call_file" ) or die "Cannot open output file";
open ( REGISTER, "> $register_file" ) or die "Cannot open output file";

my $generated = "\t// This file is generated by generateYCPwrappers from $header_file\n\n";
print CALL $generated;
print REGISTER $generated;

my $position = 0;

while (@exports)
{
	my %rec = %{ shift (@exports) } ;
	my $func_name = $rec { "name" };
	my $signature = $rec { "signature" };

	# handle parameters
	my @params = split /,\s*/, $rec { "params" };
	my $paramcount = 1;
	my @cppparams = ();
	my @tests = ();

	while (@params)
	{
	    my $par = shift (@params);
	    $par =~ m{(const\s*)?YCP(\w+)\s*(&\s*)?(/\*nil\*/)?};
	    my $type = $2;
	    if (defined $4) {	# #340523
		push (@tests, "// m_param$paramcount may be nil");
	    }
	    else {
		push (@tests, "if (m_param$paramcount.isNull() || m_param$paramcount->isVoid()) {ycp2error(\"Parameter %d is nil, %s is required\", $paramcount, \"$type\"); return YCPVoid();}");

	    }
	    $type = "m_param" . $paramcount . "->as" . $type . "()" ;
	    push @cppparams, $type;
	    $paramcount++;
	}
	print CALL "\t\tcase $position: // $func_name\n" .
	    "\t\t\t". join ("\n\t\t\t", @tests) . "\n" .
		"\t\t\treturn m_instance->$func_name (" . join (", ", @cppparams) . "); \n" ;

	print REGISTER "\tenterSymbol (new SymbolEntry (this, $position, " ;
	print REGISTER "\"$func_name\", SymbolEntry::c_function, Type::fromSignature (\"$signature\") ) );\n";
	print REGISTER "\t_registered_functions.push_back (\"$func_name\");\n";

	$position += 1;
}

close ( CALL );
close ( REGISTER );
