package RestfulDB::Exception;

use strict;
use warnings;
use parent 'Exception::Class::Base';

# The definitions of exceptions. All of them have to be derived from
# RestfulDB::Exception. HTTP status codes are coded for each of the
# exception classes in RestfulDB::Exception::http_status() method.

use Exception::Class (
    ConflictException       => { isa => 'RestfulDB::Exception' },
    DatabaseDoesNotExist    => { isa => 'RestfulDB::Exception' },
    DuplicateEntryException => { isa => 'RestfulDB::Exception' },
    InputException          => { isa => 'RestfulDB::Exception' },
    InternalException       => { isa => 'RestfulDB::Exception' },
    MetadatabaseException   => { isa => 'RestfulDB::Exception' },
    NotImplementedException => { isa => 'RestfulDB::Exception' },
    RecordNotFoundException => { isa => 'RestfulDB::Exception' },
    UnauthorizedException   => { isa => 'RestfulDB::Exception' },
);

sub http_status
{
    my $self = shift;

    return 409 if $self->isa( ConflictException:: );
    return 404 if $self->isa( DatabaseDoesNotExist:: );
    return 403 if $self->isa( DuplicateEntryException:: );
    return 400 if $self->isa( InputException:: );
    return 501 if $self->isa( NotImplementedException:: );
    return 404 if $self->isa( RecordNotFoundException:: );
    return 401 if $self->isa( UnauthorizedException:: );
    return 500;
}

sub status_class
{
    my $self = shift;
    return 'Client Error' if int($self->http_status / 100) == 4;
    return 'Server Error';
}

sub status_name
{
    my $self = shift;
    return "Conflict" if $self->isa( ConflictException:: );
    return "Forbidden" if $self->isa( DuplicateEntryException:: );
    return "Bad Request" if $self->isa( InputException:: );
    return "Not Implemented" if $self->isa( NotImplementedException:: );
    return "Not Found" if $self->isa( DatabaseDoesNotExist:: ) ||
                          $self->isa( RecordNotFoundException:: );
    return "Unauthorized" if $self->isa( UnauthorizedException:: );
    return "Internal Server Error";
}

# See:
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#Client_error_responses
sub status_info_url
{
    my $self = shift;
    return "https://tools.ietf.org/html/rfc7231#section-6.5.1"
        if $self->isa( InputException:: );
    return "https://tools.ietf.org/html/rfc7231#section-6.6.2"
        if $self->isa( NotImplementedException:: );
    return "https://tools.ietf.org/html/rfc7231#section-6.5.4"
        if $self->isa( DatabaseDoesNotExist:: ) ||
           $self->isa( RecordNotFoundException:: );
    return "https://tools.ietf.org/html/rfc7235#section-3.1"
        if $self->isa( UnauthorizedException:: );
    return "https://tools.ietf.org/html/rfc7231#section-6.6.1";
}

sub suggested_solution
{
    my $self = shift;
    return "Please refer to the API manual."
        if $self->isa( ConflictException:: ) ||
           $self->isa( DuplicateEntryException:: ) ||
           $self->isa( InputException:: );
    return "Please check the manual for the list of implemented features."
        if $self->isa( NotImplementedException:: );
    return "Please check the entered URL."
        if $self->isa( DatabaseDoesNotExist:: ) ||
           $self->isa( RecordNotFoundException:: );
    return "Please login to perform the task."
        if $self->isa( UnauthorizedException:: );
    return "Something went terribly wrong. Please contact " .
           "the site administrator to resolve this issue.";
}

1;
