package HaCi::RESTWrapper;

# REST wrapper for HaCi XML-RPC-API
#
# The methods and parameters are equal to the XML-RPC-API
#
# Authentication: 
#  * via HTTP basic authentication
#  * via username and password parameter
# 
# USAGE: 
#	 * http(s)://$hostname/RESTWrapper/[API-METHOD]?username=<user>&password=<password>&[API-PARAMETER]
#	 * http(s)://<user>@<pass>\@$hostname/RESTWrapper/[API-METHOD]?[API-PARAMETER]
#
# Examples:
# 	* http(s)://foo:bar\@$hostname/RESTWrapper/search?search=test?rootName=bigRoot
# 	* http(s)://$hostname/RESTWrapper/getFreeSubnets?username=foo&password=bar&rootName=bigRoot&supernet=192.168.0.0%2f24&cidr=32&amount=3\n";
#
# Return: JSON-Object

use strict;
use warnings;

use Data::Dumper;
use Apache2::RequestRec ();
use Apache2::RequestIO ();
use Apache2::Access ();
use Apache2::Const -compile => qw(OK SERVER_ERROR HTTP_BAD_REQUEST);
use JSON ();
use URI::Query ();
use Frontier::Client ();
use Switch;

my $r;
$SIG{__DIE__}	= sub {
	my $msg	= join('', @_);
	$r->content_type('text/html');
	warn $msg;
	print $msg;
	$r->status(Apache2::Const::SERVER_ERROR);
};

sub handler {
	$r						= shift;

	$r->allow_methods(1, qw(GET));

	my $pathInfo	= $r->path_info();
	my $hostname	= $r->hostname();
	my $uq				= URI::Query->new($r->args());
	my %params		= $uq->hash();

	unless ($pathInfo =~ /^\/(\w+)$/) {
		print "
USAGE: 
	* http(s)://$hostname/RESTWrapper/[API-METHOD]?username=<user>&password=<password>&[API-PARAMETER]
	* http(s)://<user>@<pass>\@$hostname/RESTWrapper/[API-METHOD]?[API-PARAMETER]

Examples:
	* http(s)://foo:bar\@$hostname/RESTWrapper/search?search=test?rootName=bigRoot
	* http(s)://$hostname/RESTWrapper/getFreeSubnets?username=foo&password=bar&rootName=bigRoot&supernet=192.168.0.0%2f24&cidr=32&amount=3\n";

		return Apache2::Const::HTTP_BAD_REQUEST;
	}
	my $method		= $1;

	my $user					= $r->user();
	(undef, my $pass)	= $r->get_basic_auth_pw();
	$user	||= $params{username};
	$pass	||= $params{password};

	my $result	= &wrapper($hostname, $method, $user, $pass, \%params);
	$r->content_type('application/json');
	print JSON->new->allow_nonref->encode($result) unless ref($result) eq 'HASH' && $result->{omitOutput};

	return Apache2::Const::OK;
}

sub wrapper {
	my $server	= shift;
	my $method	= shift;
	my $user		= shift;
	my $pass		= shift;
	my $params	= shift;

	my $api			= new Frontier::Client(url => "http://$server/RPC2");
	my $session	= $api->call('login', [$user, $pass]);
	die 'Login failed!' unless $session;

  # warn "Params: " . Dumper($params);
	
	my @methParams	= ();
	switch ($method) {
		case "search" {
			@methParams	= qw(search state exact templateName templateQuery rootName nrOfFreeSubs withDetails);
		}
		case "getFreeSubnets" {
			@methParams	= qw(rootName supernet cidr amount);
		}
		case "getFreeSubnetsFromSearch" {
			@methParams	= qw(search state exact templateName templateQuery rootName cidr amount);
		}
		case "addNet" {
			@methParams	= qw(rootName network description state defSubnetSize templateName templateValues);
		}
		case "delNet" {
			@methParams	= qw(rootName network);
		}
		case "assignFreeSubnet" {
			@methParams	= qw(rootName supernet cidr description state defSubnetSize templateName templateValues);
		}
		case "getNetworkDetails" {
			@methParams	= qw(rootName network);
		}
		case "getSubnets" {
			@methParams	= qw(rootName supernet);
		}
		else {
			die "Unkown method '$method'\n";
		}
  }

	my @args	= ();
	foreach (@methParams) {
		push @args, $params->{$_} // '';
	}
	# warn "Calling $method with: " . join(', ', @args) . "\n";
	return $api->call($method, $session, @args);
}

1;

# vim:ts=2:sw=2:sws=2
