#!perl

use 5.010001;
use strict;
use warnings;

#use App::chart;
use Getopt::Long qw(:config no_ignore_case bundling);
use Scalar::Util qw(looks_like_number);

our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
our $DATE = '2024-02-06'; # DATE
our $DIST = 'App-tchart'; # DIST
our $VERSION = '0.061'; # VERSION

my %Opts = (
    input        => undef,
    output       => 'text',
    type         => 'bar',
    data_column  => undef,
    label_column => undef,
    chart_height => undef,
    chart_width  => undef,
    y_scale      => 'linear',
);
my $Data;

sub parse_cmdline {
    my $res = GetOptions(
        'input|i=s'        => \$Opts{input},
        'output|o=s'       => \$Opts{output},
        'type|t=s'         => \$Opts{type},
        'data-column|d=s'  => \$Opts{data_column},
        'label-column|l=s' => \$Opts{label_column},
        'chart-height|H=f' => \$Opts{chart_height},
        'chart-width|W=f'  => \$Opts{chart_width},
        'y-scale=s'        => \$Opts{y_scale},
        'version|v'        => sub {
            say "tchart version ", ($main::VERSION // '?');
            exit 0;
        },
        'help|h'     => sub {
            print <<USAGE;
Usage:
  tchart [OPTIONS] < INPUT
  tchart --version
  tchart --help
Examples:
  tchart -o YAML < data.json
Options:
  --input=s, -i        Input data format (json, yaml, perl; default is json).
  --output=s, -o       Output format (text).
  --type=s, -t         Choose chart type.
  --data-column=s, -d
  --label-column=s, -l
  --chart-height=f, -H
  --chart-width=f, -W
Consult manpage/documentation for more details.
USAGE
            exit 0;
        },
    );
    exit 99 if !$res;
}

sub get_input {
    if (@ARGV) {
        $Data = [@ARGV];
        return;
    }

    my @lines = <>;

    my $fmt = $Opts{input};
    if (!$fmt) {
        if (looks_like_number($lines[0]) || $lines[0] =~ /\t/) {
            $fmt = "tsv";
        } else {
            $fmt = "json";
        }
    }

    if ($fmt eq 'tsv') {
        $Data = [];
        for my $line (@lines) {
            chomp $line;
            push @$Data, [split(/\t/, $line)];
        }
    } elsif ($fmt eq 'tsv+h') {
        # for now, we encode as
        my @colnames;
        if (my $firstline = shift @lines) {
            chomp $firstline;
            @colnames = split /\t/, $firstline;
        }
        $Data = [];
        for my $line (@lines) {
            chomp $line;
            my $row = [split /\t/, $line];
            push @$Data, { map { $colnames[$_] => $row->[$_]} 0..@$row-1 };
        }
    } elsif ($fmt eq 'json') {
        require JSON::MaybeXS;
        require Perinci::Result::Util;
        $Data = JSON::MaybeXS->new->allow_nonref->decode(join "", @lines);
        $Data = $Data->[2] if Perinci::Result::Util::is_env_res($Data);
    } elsif ($fmt eq 'yaml') {
        require Perinci::Result::Util;
        require YAML::Syck;
        $Data = YAML::Syck::Load(join "", @lines);
        $Data = $Data->[2] if Perinci::Result::Util::is_env_res($Data);
    } elsif ($fmt eq 'perl') {
        $Data = eval(join "", @lines); ## no critic: BuiltinFunctions::ProhibitStringyEval
    } else {
        warn "Unknown input format, ".
            "refer to documentation for available formats\n";
        exit 99;
    }
}

sub display_chart {
    if ($Opts{output} eq 'dump') {
        require JSON::MaybeXS;
        require Data::TableData::Object;
        my $tbl = Data::TableData::Object->new($Data);
        print JSON::MaybeXS->new->pretty->encode($tbl->as_aohos);
    } else {
        require Text::Chart;
        binmode(STDOUT, ":encoding(utf8)");
        print Text::Chart::gen_text_chart(
            data         => $Data,
            type         => $Opts{type},
            label_column => $Opts{label_column},
            data_column  => $Opts{data_column},
            chart_height => $Opts{chart_height},
            chart_width  => $Opts{chart_width},
            show_data_label => 1,
            show_data_value => 1,
            #y_scale      => $Opts{y_scale},
        );
    }
}

# MAIN

parse_cmdline();
get_input();
display_chart();

1;
# ABSTRACT: Create chart for your data structure
# PODNAME: tchart

__END__

=pod

=encoding UTF-8

=head1 NAME

tchart - Create chart for your data structure

=head1 VERSION

This document describes version 0.061 of tchart (from Perl distribution App-tchart), released on 2024-02-06.

=head1 SYNOPSIS

Usage:

 % tchart [OPTIONS] NUMBER ...
 % tchart [OPTIONS] < INPUT

Examples:

 % echo '[1,5,10,2,4,6]' | tchart -t sparkline

 % tchart -t sparkline 1 5 10 2 4 6

 % cat celine-dion-album-sales.json
 [
   {
     "lang": "en",
     "sales": 3000000,
     "title": "unison",
     "year": 1990
   },
   {
     "lang": "en",
     "sales": 5300000,
     "title": "celine dion",
     "year": 1992
   },
   {
     "lang": "en",
     "sales": 16600000,
     "title": "the color of my love",
     "year": 1993
   },
   ...
 ]

 % tchart -l year -d sales celine-dion-album-sales.json
 1990|**                                            ( 3000000)
 1992|******                                        ( 5300000)
 1993|**********************                        (16600000)
 1996|******************************************    (30300000)
 1997|********************************************* (32100000)
 1998|****************                              (12100000)
 2002|*************                                 (10500000)
 2003|******                                        ( 5100000)
 2004|**                                            ( 2600000)
 2007|***                                           ( 3400000)
 2013|                                              ( 1300000)

=head1 DESCRIPTION

This program creates a chart for your data structure, either in the form of an
array, array of arrays, hash, array of hashes. You can use it to quickly
visualize a data structure on a console.

It accepts input as JSON, or several other alternative formats (see the C<-i>
option). It by default outputs the chart as ASCII text. Other formats will be
supported in the future.

This is an early release. More options, chart types, will be added in the
future.

=head1 EXIT CODES

0 on success.

1 on failure.

99 on command-line options error.

=head1 OPTIONS

=over

=item * --input=STR, -i

Pick input format. Available formats: C<tsv> (tab-separated, with no header
line), C<tsv+h> (tab-separated, with header line), C<json> (parsed using
L<JSON>), C<yaml> (parsed using L<YAML::Syck>), C<perl> (eval-ed by B<perl>).
Default is detected using simple heuristics.

=item * --output=STR, -o

Pick output chart format. Available formats: text, dump. Default is text.

=item * --data-column, -d

=item * --label-column, -l

=item * --type, -t

Pick chart type. Available type: C<line>, C<bar>, C<sparkline>. Default is
C<bar>.

=back

=head1 FAQ

=head1 HOMEPAGE

Please visit the project's homepage at L<https://metacpan.org/release/App-tchart>.

=head1 SOURCE

Source repository is at L<https://github.com/perlancar/perl-App-tchart>.

=head1 SEE ALSO

L<Text::Chart>

=head1 AUTHOR

perlancar <perlancar@cpan.org>

=head1 CONTRIBUTING


To contribute, you can send patches by email/via RT, or send pull requests on
GitHub.

Most of the time, you don't need to build the distribution yourself. You can
simply modify the code, then test via:

 % prove -l

If you want to build the distribution (e.g. to try to install it locally on your
system), you can install L<Dist::Zilla>,
L<Dist::Zilla::PluginBundle::Author::PERLANCAR>,
L<Pod::Weaver::PluginBundle::Author::PERLANCAR>, and sometimes one or two other
Dist::Zilla- and/or Pod::Weaver plugins. Any additional steps required beyond
that are considered a bug and can be reported to me.

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2024, 2016, 2014 by perlancar <perlancar@cpan.org>.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=head1 BUGS

Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=App-tchart>

When submitting a bug or request, please include a test-file or a
patch to an existing test-file that illustrates the bug or desired
feature.

=cut
