package WWW::Marvel::Client;
use base qw/ Class::Accessor /;
use Carp;
use Digest::MD5;
use JSON;
use LWP::UserAgent;
use URI;
__PACKAGE__->follow_best_practice;
__PACKAGE__->mk_accessors(qw/ public_key private_key timestamp /);

sub get_endpoint    { "http://gateway.marvel.com" }
sub get_api_version { "v1" }

sub characters {
	my ($self, $params) = @_;
	my %p = %$params;
	my $uri = $self->uri({ path => 'characters', params => \%p });
	my $http_res = $self->_get_http_res($uri);
	return $self->_get_json_content($http_res);
}

sub _get_http_res {
	my ($self, $uri) = @_;
	my $http_res = $self->ua->get($uri);
	croak $http_res->status_line if !$http_res->is_success;
	return $http_res;
}

sub _get_json_content {
	my ($self, $http_res) = @_;
	my $json = JSON->new();
	my $content = $json->allow_nonref->relaxed->decode( $http_res->decoded_content );
	return $content;
}

# ref: https://developer.marvel.com/documentation/authorization
sub hash {
	my ($self, $time) = @_;

	if (!defined $time) {
		croak "need a timestamp to create a md5 hash" if !defined $self->get_timestamp;
		$time = $self->get_timestamp;
	}

	my $md5 = Digest::MD5->new;
	$md5->add( $time, $self->get_private_key, $self->get_public_key );
	return $md5->hexdigest;
}

sub ua { LWP::UserAgent->new() }

sub uri {
	my ($self, $args) = @_;

	my $time = $self->get_timestamp || time;

	my @paths;
	if (exists $args->{path} && ref $args->{path} eq 'ARRAY') {
		@paths = @{ $args->{path} };
	}
	elsif (exists $args->{path} && ref $args->{path} eq '') {
		push(@paths, $args->{path});
	}

	my %params;
	if (exists $args->{params} && ref $args->{params} eq 'HASH') {
		%params = %{ $args->{params} };
	}

	my %query_params = (
		%params,
		ts     => $time,
		hash   => $self->hash($time),
		apikey => $self->get_public_key,
	);

	my $uri = URI->new( $self->get_endpoint );
	$uri->path( $self->uri_path(@paths) );
	$uri->query_form(%query_params);
	return $uri;
}

sub uri_path {
	my ($self, @resources) = @_;
	croak "need a resource to query" if @resources < 1;
	return join('/', $self->get_api_version, 'public', @resources );
}

1;
