#!/usr/bin/perl -w
use strict;
use warnings;
use Text::CSV;
use IO::Handle;
# use Fcntl;

if (!$ENV{opts_got}) {
    exec 'o', $0, @ARGV;
    die "csvjoin: could not exec config loader: o\n";
}

my $head = $ENV{head};
my $dos = $ENV{dos};
my $flush = $ENV{flush};
my $align = $ENV{align};
my $sep = $ENV{sep};
# my $always_quote = $ENV{quote};
my $eol = $dos ? "\r\n" : "\n";
my $pretty_head = $head eq 'pretty';

my @inputs = @ARGV;
my @in_fhs;
for my $i (0..$#inputs) {
    my $file = $inputs[$i];
#    warn "opening $file";
    # it SUCKS that named pipes block on open, so have to open in same order in writer and reader processes!
    # hack around with a cat for each port!  :S
#    open my $fh, "cat \Q$file\E |";
    # It seems we can avoid this problem by opening output ports before input ports where possible, and by adding "cat" or buffer processes manually where necessary.
    open my $fh, "<", $file;

#    sysopen my $fh, $file, O_RDONLY | O_NONBLOCK
#        or die "csvjoin: open failed <$file: $!\n";
#    $fh->blocking(1);
#my $flags = fcntl($fh, F_GETFL, 0)
#	or die "Can't get flags for the input: $!\n";

#$flags = fcntl($fh, F_SETFL, $flags & ~O_NONBLOCK)
#	or die "Can't set flags for the input: $!\n";

    $in_fhs[$i] = $fh;
}

# my $csv = Text::CSV->new({ binary => 1, always_quote => $always_quote, blank_is_undef => 1 })
my $csv = Text::CSV->new({ binary => 1, sep_char => $sep })
    or die "csvjoin: Cannot use CSV: ".Text::CSV->error_diag;
$csv->eol($eol);

my $out = \*STDOUT;
binmode($out, ":utf8");
if ($flush) {
    $out->autoflush;
}

sub pretty_name {
    my ($name) = @_;
    $name =~ s/_/ /g unless $name =~ /\A_|_\z/;
    return $name;
}

if ($head) {
    my $header;
    if ($pretty_head) {
        $header = [map { pretty_name($_) } @inputs];
    } else {
        $header = [@inputs];
    }
    $csv->print($out, $header);
}

while(1) {
    my @row;
    my $have_1 = 0;
    my $have_all = 1;
    for my $i (0..$#inputs) {
	my $fh = $in_fhs[$i];
        my $x = scalar <$fh>;
        if (defined $x) {
            $have_1 = 1;
        } else {
            $have_all = 0;
            $x = '';
        }
        chomp $x;
        push @row, $x;
    }
    if (!$have_1) {
        last;
    }
    if (!$have_all && $align) {
        die "csvjoin: input channels did not all eof together\n";
        # TODO show partial row on STDERR?
    }
    $csv->print($out, \@row);
}
