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 Data::Structure::Util qw(unbless);
use Scalar::Util qw/blessed/;
use Storable qw/dclone/;
use Carp qw/carp/;

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 rev {
	my ($self,$url) = @_;
	my $rev = $rev->{$url};
	$rev  ||= eval { $self->get( $url )->{_rev} };
#	warn "# rev $url $rev";
	return $rev;
}

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

	$self->request(DELETE => $url . '?rev=' . $self->rev($url) );
}

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

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

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

	$json->{_rev} = $rev->{$url} if defined $rev->{$url};

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

#	warn "# put ",dump( $data );

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

	carp "# put ",$json;

	do {
		my $json = eval { $self->request(PUT => $url, $json) };
		if ( $@ ) {
			$rev->{$url} = $self->rev( $url );
			warn "refresh rev $url = ", $rev->{$url};
		} else {
			$rev->{$url} = JSON->new->decode( $json )->{rev};
		}
	} until ! $@;
}

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

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

our $audit = __PACKAGE__->new;

sub _store_audit {
	my ( $id, $data ) = @_;
	$audit->put( "pxelator/$id", $data );
}

1;
