The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
package Catmandu::Exporter::CSV;

use Catmandu::Sane;
use Moo;
use Text::CSV;

with 'Catmandu::Exporter';

has csv         => (is => 'ro', lazy => 1, builder => '_build_csv');
has sep_char    => (is => 'ro', default => sub { ',' });
has quote_char  => (is => 'ro', default => sub { '"' });
has escape_char => (is => 'ro', default => sub { '"' });
has header      => (is => 'rw', default => sub { 1 });
has fields => (
    is     => 'rw',
    coerce => sub {
        my $fields = $_[0];
        given (ref $fields) {
            when ('ARRAY') { return $fields }
            when ('HASH')  { return [keys %$fields] }
            default        { return [split ',', $fields] }
        }
    },
);

sub _build_csv {
    my ($self) = @_;
    Text::CSV->new({
        binary => 1,
        eol => "\n",
        sep_char => $self->sep_char,
        quote_char => $self->quote_char ? $self->quote_char : undef,
        escape_char => $self->escape_char ? $self->escape_char : undef,
    });
}

sub add {
    my ($self, $data) = @_;
    my $fields = $self->fields || $self->fields($data);
    my $row = [map {
        my $val = $data->{$_} // "";
        $val =~ s/\t/\\t/g;
        $val =~ s/\n/\\n/g;
        $val =~ s/\r/\\r/g;
        $val;
    } @$fields];
    my $fh = $self->fh;
    if ($self->count == 0 && $self->header) {
        $self->csv->print($fh, ref $self->header
            ? [map { $self->header->{$_} // $_ } @$fields]
            : $fields);
    }
    $self->csv->print($fh, $row);
}

=head1 NAME

Catmandu::Exporter::CSV - a CSV exporter

=head1 SYNOPSIS

    use Catmandu::Exporter::CSV;

    my $exporter = Catmandu::Exporter::CSV->new(
				fix => 'myfix.txt'
				quote_char => '"' ,
				sep_char => ',' ,
				header => 1);

    $exporter->fields("f1,f2,f3");
    $exporter->fields([qw(f1 f2 f3)]);

    # add custom header labels
    $exporter->header({f2 => 'field two'});

    $exporter->add_many($arrayref);
    $exporter->add_many($iterator);
    $exporter->add_many(sub { });

    $exporter->add($hashref);

    printf "exported %d objects\n" , $exporter->count;

=head1 METHODS

=head2 new(quote_char => STRING, sep_char => STRING, header => 0|1|HASH, fields => ARRAY|HASH|STRING)

Creates a new Catmandu::Exporter::CSV. Optionally set the field and column
boundaries with quote_char and sep_char. A header line with field names will be
included if C<header> is set. Field names can be read from the first item
exported or set by the fields argument (see: C<fields>).

=head2 fields($arrayref)

Set the field names by an ARRAY reference.

=head2 fields($hashref)

Set the field names by the keys of a HASH reference.

=head2 fields($string)

Set the fields by a comma delimited string.

=head2 header(1)

Include a header line with the field names

=head2 header($hashref)

Include a header line with custom field names

=head1 SEE ALSO

L<Catmandu::Exporter>

=cut

1;