package Net::RDAP::Object;
use List::Util qw(any);
use base qw(Net::RDAP::Base);
use strict;
use warnings;

=pod

=head1 NAME

L<Net::RDAP::Object> - a module representing an RDAP object.

=head1 DESCRIPTION

RDAP responses contain one or more RDAP objects: typically the response
itself corresponds to an RDAP object, but RDAP objects can contain
other RDAP objects (such as the entities and nameservers associated
with a domain name).

L<Net::RDAP::Object> represents such objects, whether top-level or
embedded. It inherits from L<Net::RDAP::Base> so has all the methods
available to that module.

=cut

#
# Constructor method. $args is a hashref, $url is the URL this
# object was loaded from
#
sub new {
    my ($package, $args, $document_url, $parent) = @_;

    return $package->SUPER::new($args, $document_url, $parent);
}

=pod

=head1 METHODS

=head2 RDAP Conformance

    @conformance = $response->conformance;

Returns an array of strings, each providing a hint as to the
specifications used (by the server) in the construction of the response.

This method will return C<undef> unless called on the top-most object
in a response.

=cut

sub conformance {
    my $self = shift;
    return @{$self->{'rdapConformance'} || []};
}

=pod

=head2 Notices

    @notices = $response->notices;

Returns a (potentially empty) array of L<Net::RDAP::Notice> objects.

The array will always be empty unless called on the top-most object
in a response.

=cut

sub notices { $_[0]->objects('Net::RDAP::Notice', $_[0]->{'notices'}) }

=pod

=head2 Object Class

    $class = $object->class;

Returns a string containing the "class name" of this object (i.e., one
of: C<ip network>, C<entity>, C<nameserver>, C<autnum> or C<domain>).

=cut

sub class { $_[0]->{'objectClassName'} }

=pod

=head2 Handle

    $handle = $object->handle;

Returns a string containing the "handle" of the object.

=cut

sub handle { $_[0]->{'handle'} }

=pod

=head2 Status

    @status = $object->status;

Returns a (potentially empty) array of state identifiers. The possible
values are defined by bn IANA registry; see:

=over

=item * L<https://www.iana.org/assignments/rdap-json-values/rdap-json-values.xhtml>

=back

=cut

sub status { $_[0]->{'status'} ? @{$_[0]->{'status'}} : () }

=pod

=head2 Remarks

    @remarks = $object->remarks;

Returns a (potentially empty) array of L<Net::RDAP::Remark> objects.

=cut

sub remarks { $_[0]->objects('Net::RDAP::Remark', $_[0]->{'remarks'}) }

=pod

=head2 Events

    @events = $object->events;

Returns a (potentially empty) array of L<Net::RDAP::Event> objects.

=cut

sub events { $_[0]->objects('Net::RDAP::Event', $_[0]->{'events'}) }

=pod

    $event = $object->event($action);

Returns the first L<Net::RDAP::Event> object whose C<action> property
matches C<$action> (or C<undef> if no such event is found).

=cut

sub event {
    my ($self, $action) = @_;

    return [ grep { $_->action eq $action } $self->events ]->[0];
}

=pod

=head2 Port-43 Whois Server

    $port43 = $object->port43;

Returns a L<Net::DNS::Domain> object containing the name of the
legacy port-43 whois server for this object.

=cut

sub port43 { $_[0]->{'port43'} }

=pod

=head2 Public IDs

    @ids = $object->ids;

Returns a (potentially empty) array of L<Net::RDAP::ID> objects.

=cut

sub ids { $_[0]->objects('Net::RDAP::ID', $_[0]->{'publicIds'}) }

=pod

=head2 Entities

    @entities = $object->entities;

Returns a (potentially empty) array of L<Net::RDAP::Object::Entity> objects.

=cut

sub entities { $_[0]->objects('Net::RDAP::Object::Entity', $_[0]->{'entities'}) }

=pod

    $entity = $object->entity($role);

Returns the first L<Net::RDAP::Object::Entity> object whose C<roles> property
contains C<$role> (or C<undef> if no such entity is found).

    $registrant = $object->registrant;

Alias for C<$object-E<gt>entity('registrant')>.

    $registrar = $object->registrar;

Alias for C<$object-E<gt>entity('registrar')>.

=cut

sub entity {
    my ($self, $role) = @_;

    return [ grep { $_->has_role($role) } $self->entities ]->[0];
}

sub registrant { shift->entity(q{registrant}) }
sub registrar  { shift->entity(q{registrar}) }

=pod

=head2 Redactions

    @redactions = $object->redactions;

If the server supports L<RFC 9537|https://www.rfc-editor.org/rfc/rfc9537.html>,
then this method will return an array of L<Net::RDAP::Redaction> objects
corresponding to the fields listed in the C<redacted> property of the object.

=cut

sub redactions { $_[0]->objects('Net::RDAP::Redaction', $_[0]->{'redacted'}) }

=pod

=head1 TTL values

	$ttl = $domain->dns_ttl("NS");
	$ttl = $host->dns_ttl("AAAA");

If the server supports
L<draft-ietf-regext-rdap-ttl-extension|https://datatracker.ietf.org/doc/draft-ietf-regext-rdap-ttl-extension/>,
this method returns a number representing the Time-To-Live (TTL) (in seconds) of
the DNS record(s) of the specified type that are published in the DNS for the
given domain or nameserver object. Returns C<undef> if the server does not
support this extension, or if no values are available for the given type. Not
applicable to entities.

=cut

sub dns_ttl {
	my ($self, $type) = @_;

	return $self->{'ttl0_data'}->{'values'}->{$type};
}

=pod

	@types = $domain_or_host->dns_ttl_types;

Returns a list of the DNS record types for which TTL values are available.

=cut

sub dns_ttl_types { sort(keys(%{$_[0]->{'ttl0_data'}->{'values'}})) }

=pod

	@types = $domain_or_host->dns_ttl_remarks;

Returns a list of L<Net::RDAP::Remark> objects relating to the TTL values of the
object.

=cut

sub dns_ttl_remarks { $_[0]->objects('Net::RDAP::Remark', $_[0]->{'ttl0_data'}->{'remarks'}) }

=pod

=head1 Extensions

	$object->has_extension($extn);

This method returns true if the RDAP extension identied by C<$extn> is present
in the C<rdapConformance> property. This method only works on the topmost object
of a response.

=cut

sub has_extension { any { $_ eq $_[1] } $_[0]->conformance }

=pod

=head1 COPYRIGHT

Copyright 2018-2023 CentralNic Ltd, 2024-2026 Gavin Brown. For licensing information,
please see the C<LICENSE> file in the L<Net::RDAP> distribution.

=cut

1;
