package CouchDB;

# http://wiki.apache.org/couchdb/Getting_started_with_Perl

use strict;
use warnings;

use LWP::UserAgent;
use JSON;
use Data::Dump qw/dump/;
use Time::HiRes qw/time/;
use Data::Structure::Util qw(unbless);
use Scalar::Util qw/blessed/;
use Storable qw/dclone/;

sub new {
	my ($class, $host, $port, $options) = @_;

	my $ua = LWP::UserAgent->new;
	$ua->timeout(10);
	$ua->env_proxy;

	$host ||= 'localhost';
	$port ||= 5984;

	return bless {
		ua			 => $ua,
		host		 => $host,
		port		 => $port,
		base_uri => "http://$host:$port/",
	}, $class;
}

sub ua { shift->{ua} }
sub base { shift->{base_uri} }

sub request {
	my ($self, $method, $uri, $content) = @_;

	my $full_uri = $self->base . $uri;
	my $req;

	if (defined $content) {
		#Content-Type: application/json

		$req = HTTP::Request->new( $method, $full_uri, undef, $content );
		$req->header('Content-Type' => 'application/json');
	} else {
		$req = HTTP::Request->new( $method, $full_uri );
	}

	my $response = $self->ua->request($req);

	if ($response->is_success) {
		return $response->content;
	} else {
		die($response->status_line . ":" . $response->content);
	}
}

our $rev;

sub delete {
	my ($self, $url) = @_;

	$self->request(DELETE => $url);
}

sub get {
	my ($self, $url) = @_;

	JSON->new->utf8->decode( $self->request(GET => $url) );
}

sub put {
	my ($self, $url, $json) = @_;

	if ( ! defined $json->{_rev} ) {
		my $old = eval { $self->get( $url )->{_rev} };
		$rev->{$url} = $json->{_rev} = $old if defined $old;
	}

	$json = unbless dclone $json if blessed $json;

	$json = JSON->new->utf8->encode( $json ) if $json;

	$self->request(PUT => $url, $json);
}

sub post {
	my ($self, $url, $json) = @_;

	$self->request(POST => $url, $json);
}

our $audit = __PACKAGE__->new;

sub audit {
	my $data = pop @_;

	my $url = join(' ', @_);
	$url =~ s/-\S+//g;
	$url =~ s/\W+/-/g;

	my ( $package, $file, $line, $sub ) = caller(1);
	( $package, undef, $line ) = caller(0) if $package eq 'main';

	my $t = time();

	$data->{x_meta} = {
		'time' => $t,
		'package' => $package,
		'line' => $line,
		'sub' => $sub,
	};
	$data->{'ident'} = [ @_ ] if @_;

	warn 'audit ', dump($data), "at $file +$line\n";

	$audit->put( "pxelator/$t.$package.$url", $data );
}

1;
