#!/usr/bin/env perl

# Copyright (c) 2015 Christian Jaeger, copying@christianjaeger.ch
# This is free software. See the file COPYING.md that came bundled
# with this file.

use strict;
use warnings;
use warnings FATAL => 'uninitialized';

# find modules from functional-perl working directory (not installed)
use Cwd 'abs_path';
our ($mydir, $myname);

BEGIN {
    my $location = (-l $0) ? abs_path($0) : $0;
    $location =~ /(.*?)([^\/]+?)_?\z/s or die "?";
    ($mydir, $myname) = ($1, $2);
}
use lib "$mydir/../lib";

sub usage {
    print "usage: $myname [-o xmlfile] csvfile(s)

  Open and read csvfile containing CSV with 4 columns, and write it to
  xmlfile or stdout as XML. Does streaming, i.e. only loads one row
  (plus some buffering) into memory at a time.

";
    exit(@_ ? 1 : 0);
}

use Getopt::Long;
our $verbose = 0;
our $outpath;
GetOptions(
    "verbose"   => \$verbose,
    "help"      => sub {usage},
    "outpath=s" => \$outpath,
) or exit 1;
usage unless @ARGV;

use FP::Text::CSV qw(csv_file_to_rows);

use PXML::Tags

    # create tag functions for the following XML tag names. Casing is
    # preserved for the output, but the tag functions are all-uppercase
    # (to try to avoid name conflicts and for better visibility) and
    # replace the minus with the underscore.
    qw(myexample
    protocol-version
    records
    record
    a
    b
    c
    d);

use PXML::Serialize qw(pxml_print);

sub print_csv_as_xml {
    my ($fh, $path) = @_;

    my $rows = csv_file_to_rows $path, +{ eol => "\n", sep_char => ";" };

    # $rows is a lazily-computed linked list of the rows

    # skip the header row from the CSV file:
    $rows = rest $rows;

    # create a partially lazily computed PXML data structure
    my $xmlstream = MYEXAMPLE(
        PROTOCOL_VERSION("0.123"),
        RECORDS    # here we embed the lazily computed part:
            (
            $rows->map (
                sub {
                    my ($row) = @_;
                    @$row == 4 or die "row doesn't contain 4 columns: @$row";
                    my ($a, $b, $c, $d) = @$row;

                    RECORD(A($a), B($b), C($c), D($d))
                }
            )
            )
    );

    # walk and print the PXML data structure, forcing its evaluation
    # as needed
    pxml_print $xmlstream, $fh;
}

use Chj::xtmpfile;
use Chj::xopen qw(glob_to_fh);

my $fh = defined $outpath ? xtmpfile $outpath : glob_to_fh * STDOUT;
print_csv_as_xml $fh, $_ for @ARGV;
$fh->xclose;
$fh->xputback(0666 & ~umask) if defined $outpath;

