package Venus::Role::Printable;

use 5.018;

use strict;
use warnings;

use Venus::Role 'fault';

# AUDITS

sub AUDIT {
  my ($self, $from) = @_;

  if (!$from->does('Venus::Role::Dumpable')) {
    fault "${self} requires ${from} to consume Venus::Role::Dumpable";
  }

  return $self;
}

# METHODS

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

  return $self->printer($self->dump(@args));
}

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

  require Venus::Json;

  my $value = $method ? scalar($self->$method(@args)) : $self;

  require Scalar::Util;

  if (Scalar::Util::blessed($value)) {
    $value = $value->value if $value->isa('Venus::Kind');
  }

  return $self->printer(Venus::Json->new($value)->encode);
}

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

  return $self->printer($self->dump_pretty(@args));
}

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

  local $_ = $self;

  return $self->printer($method ? scalar($self->$method(@args)) : $self);
}

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

  require Venus::Yaml;

  my $value = $method ? scalar($self->$method(@args)) : $self;

  require Scalar::Util;

  if (Scalar::Util::blessed($value)) {
    $value = $value->value if $value->isa('Venus::Kind');
  }

  return $self->printer(Venus::Yaml->new($value)->encode);
}

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

  return CORE::print(STDOUT @args);
}

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

  return $self->printer($self->dump(@args), "\n");
}

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

  require Venus::Json;

  my $value = $method ? scalar($self->$method(@args)) : $self;

  require Scalar::Util;

  if (Scalar::Util::blessed($value)) {
    $value = $value->value if $value->isa('Venus::Kind');
  }

  return $self->printer(Venus::Json->new($value)->encode, "\n");
}

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

  return $self->printer($self->dump_pretty(@args), "\n");
}

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

  local $_ = $self;

  return $self->printer(($method ? scalar($self->$method(@args)) : $self), "\n");
}

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

  require Venus::Yaml;

  my $value = $method ? scalar($self->$method(@args)) : $self;

  require Scalar::Util;

  if (Scalar::Util::blessed($value)) {
    $value = $value->value if $value->isa('Venus::Kind');
  }

  return $self->printer(Venus::Yaml->new($value)->encode, "\n");
}

# EXPORTS

sub EXPORT {
  [
    'print',
    'print_json',
    'print_pretty',
    'print_string',
    'print_yaml',
    'printer',
    'say',
    'say_json',
    'say_pretty',
    'say_string',
    'say_yaml',
  ]
}

1;



=head1 NAME

Venus::Role::Printable - Printable Role

=cut

=head1 ABSTRACT

Printable Role for Perl 5

=cut

=head1 SYNOPSIS

  package Example;

  use Venus::Class;

  with 'Venus::Role::Dumpable';
  with 'Venus::Role::Printable';

  attr 'test';

  sub execute {
    return [@_];
  }

  sub printer {
    return [@_];
  }

  package main;

  my $example = Example->new(test => 123);

  # $example->say;

=cut

=head1 DESCRIPTION

This package provides a mechanism for outputting (printing) objects or the
return value of a dispatched method call to STDOUT.

=cut

=head1 METHODS

This package provides the following methods:

=cut

=head2 print

  print(Any @data) (Any)

The print method prints a stringified representation of the underlying data.

I<Since C<0.01>>

=over 4

=item print example 1

  package main;

  my $example = Example->new(test => 123);

  my $print = $example->print;

  # bless({test => 123}, 'Example')

  # 1

=back

=over 4

=item print example 2

  package main;

  my $example = Example->new(test => 123);

  my $print = $example->print('execute', 1, 2, 3);

  # [bless({test => 123}, 'Example'),1,2,3]

  # 1

=back

=cut

=head2 print_json

  print_json(Str | CodeRef $method, Any @args) (Any)

The print_json method prints a JSON representation of the underlying data. This
method supports dispatching, i.e. providing a method name and arguments whose
return value will be acted on by this method.

I<Since C<2.91>>

=over 4

=item print_json example 1

  package main;

  my $example = Example->new(test => 123);

  my $print_json = $example->print_json;

  # "{\"test\": 123}"

=back

=over 4

=item print_json example 2

  package main;

  my $example = Example->new(test => 123);

  my $print_json = $example->print_json('execute');

  # "[{\"test\": 123}]"

=back

=cut

=head2 print_pretty

  print_pretty(Any @data) (Any)

The print_pretty method prints a stringified human-readable representation of
the underlying data.

I<Since C<0.01>>

=over 4

=item print_pretty example 1

  package main;

  my $example = Example->new(test => 123);

  my $print_pretty = $example->print_pretty;

  # bless({ test => 123 }, 'Example')

  # 1

=back

=over 4

=item print_pretty example 2

  package main;

  my $example = Example->new(test => 123);

  my $print_pretty = $example->print_pretty('execute', 1, 2, 3);

  # [
  #   bless({ test => 123 }, 'Example'),
  #   1,
  #   2,
  #   3
  # ]

  # 1

=back

=cut

=head2 print_string

  print_string(Str | CodeRef $method, Any @args) (Any)

The print_string method prints a string representation of the underlying data
without using a dump. This method supports dispatching, i.e. providing a
method name and arguments whose return value will be acted on by this method.

I<Since C<0.09>>

=over 4

=item print_string example 1

  package main;

  my $example = Example->new(test => 123);

  my $print_string = $example->print_string;

  # 'Example'

  # 1

=back

=cut

=head2 print_yaml

  print_yaml(Str | CodeRef $method, Any @args) (Any)

The print_yaml method prints a YAML representation of the underlying data. This
method supports dispatching, i.e. providing a method name and arguments whose
return value will be acted on by this method.

I<Since C<2.91>>

=over 4

=item print_yaml example 1

  package main;

  my $example = Example->new(test => 123);

  my $print_yaml = $example->print_yaml;

  # "---\ntest: 123"

=back

=over 4

=item print_yaml example 2

  package main;

  my $example = Example->new(test => 123);

  my $print_yaml = $example->print_yaml('execute');

  # "---\n- test: 123"

=back

=cut

=head2 say

  say(Any @data) (Any)

The say method prints a stringified representation of the underlying data, with
a trailing newline.

I<Since C<0.01>>

=over 4

=item say example 1

  package main;

  my $example = Example->new(test => 123);

  my $say = $example->say;

  # bless({test => 123}, 'Example')\n

  # 1

=back

=over 4

=item say example 2

  package main;

  my $example = Example->new(test => 123);

  my $say = $example->say;

  # [bless({test => 123}, 'Example'),1,2,3]\n

  # 1

=back

=cut

=head2 say_json

  say_json(Str | CodeRef $method, Any @args) (Any)

The say_json method prints a JSON representation of the underlying data. This
method supports dispatching, i.e. providing a method name and arguments whose
return value will be acted on by this method, with a trailing newline.

I<Since C<2.91>>

=over 4

=item say_json example 1

  package main;

  my $example = Example->new(test => 123);

  my $say_json = $example->say_json;

  # "{\"test\": 123}\n"

=back

=over 4

=item say_json example 2

  package main;

  my $example = Example->new(test => 123);

  my $say_json = $example->say_json('execute');

  # "[{\"test\": 123}]\n"

=back

=cut

=head2 say_pretty

  say_pretty(Any @data) (Any)

The say_pretty method prints a stringified human-readable representation of the
underlying data, with a trailing newline.

I<Since C<0.01>>

=over 4

=item say_pretty example 1

  package main;

  my $example = Example->new(test => 123);

  my $say_pretty = $example->say_pretty;

  # bless({ test => 123 }, 'Example')\n

  # 1

=back

=over 4

=item say_pretty example 2

  package main;

  my $example = Example->new(test => 123);

  my $say_pretty = $example->say_pretty;

  # [
  #   bless({ test => 123 }, 'Example'),
  #   1,
  #   2,
  #   3
  # ]\n

  # 1

=back

=cut

=head2 say_string

  say_string(Str | CodeRef $method, Any @args) (Any)

The say_string method prints a string representation of the underlying data
without using a dump, with a trailing newline. This method supports
dispatching, i.e. providing a method name and arguments whose return value will
be acted on by this method.

I<Since C<0.09>>

=over 4

=item say_string example 1

  package main;

  my $example = Example->new(test => 123);

  my $say_string = $example->say_string;

  # "Example\n"

  # 1

=back

=cut

=head2 say_yaml

  say_yaml(Str | CodeRef $method, Any @args) (Any)

The say_yaml method prints a YAML representation of the underlying data. This
method supports dispatching, i.e. providing a method name and arguments whose
return value will be acted on by this method, with a trailing newline.

I<Since C<2.91>>

=over 4

=item say_yaml example 1

  package main;

  my $example = Example->new(test => 123);

  my $say_yaml = $example->say_yaml;

  # "---\ntest: 123\n"

=back

=over 4

=item say_yaml example 2

  package main;

  my $example = Example->new(test => 123);

  my $say_yaml = $example->say_yaml('execute');

  # "---\n- test: 123\n"

=back

=cut

=head1 AUTHORS

Awncorp, C<awncorp@cpan.org>

=cut

=head1 LICENSE

Copyright (C) 2000, Al Newkirk.

This program is free software, you can redistribute it and/or modify it under
the terms of the Apache license version 2.0.

=cut