#!/usr/bin/perl -w

# csv with " as text delimiter -> RIS.
# see http://en.wikipedia.org/wiki/RIS_(file_format)

# developed for CSV formatted as: (first line of csv):
# catno,url,title,tio,tiu,resp,author,corp,conf,publ,pub,year,edtn,coll,series,nd,notes,de,subj,sc,species,abstract,res,nu,isbn,issn,la,,,,
# This program actually uses the field names from the first line of the CSV,
# so it will continue to work if they are re-ordered or other fields are inserted in between.
# It will break if any fields are renamed, though.

# a lot of stuff just goes in N1, which goes straight into the procite Notes field,
# without prefixes like  User Defined 1: for U1 tags.

# copyright 2009, Peter Cordes <peter@cordes.ca>.
# share and enjoy under the terms of the GNU GPL (v2 or later)

use Text::CSV;

#use open ':crlf';  # win32 activeperl writes crlf files by default.
use open ':encoding(utf8)';
use open ':std'; # set STD* based on IN and OUT settings.  shortcut for binmode(...)

# return an RIS tag with value if we have a non-empty value.
sub tag{
    my ($tag, $val) = @_;
    if(length($val) > 0){
	return "$tag  - " . $val . "\n";
    }else{
	return "";
    }
}

#  like tag(), but adding a prefix to the value that's tested for non-0 length
sub preftag{
    my ($tag, $prefix, $val) = @_;
    if(length($val) > 0){
	return "$tag  - " . $prefix . $val . "\n";
    }else{
	return "";
    }
}


if ($ARGV[0] =~ /\.ris$/i){
    die "You ran me with a .ris file as input!\n",
    "I want to read a .csv, and write a .ris.  Refusing to create output:\n",
    "$ARGV[0].ris\n";
}
# All output goes to a .ris file named for the first input arg
# Probably won't be run with multiple args anyway
# Also note that column names are taken only from the first input file.
(my $outfile = $ARGV[0]) =~ s/\.txt$|\.csv$//i;
$outfile .= ".ris";

#open( RIS, ">", "$outfile" ) or do { warn "can't open $outfile for writing: $!\n"; next; };

open( RIS, ">", "$outfile" ) or die "can't open $outfile for writing: $!\n";
#open STDERR, ">", "$outfile.err" or do { warn "can't open $outfile.err for writing: $!\n"; next; };

my $csv = Text::CSV->new( {escape_char => '\\'} );

my $names = $csv->getline(*ARGV);
$csv->column_names( $names );

while(my $row = $csv->getline_hr(*ARGV)){


    print RIS "TY  - GEN\n", # TODO: something other than GENeric, when possible.  but procite won't use it
#    tag("ID", $row->{catno}), # procite ignores ID
    tag("N1", "WAVES CATNO:" . $row->{catno}),
    tag("UR", $row->{url}),
    tag("T1", $row->{title}), #  - Primary title # FIXME: procite uses // between list items

#    tag("TI", ??  - Book title
#    tag("CT", $row->{}), #  - Title of unpublished reference
#    tag("A1", $row->{author}), #  - Primary author
#    tag("A2", $row->{}), #  - Secondary author (each name on separate line)

    tag("AU", $row->{author}), #  - Author (syntax. Last name, First name, Suffix) # FIXME: could loop over split /\s*;\s*/
#Y1  - Primary date
    tag("PY", $row->{year}), #  - Publication year (YYYY/MM/DD)
    tag("N1", $row->{notes}), #  - Notes
    tag("SP", $row->{coll}), #  - Start page number
    tag("T3", $row->{series}), #  - Title series
    preftag("N1", "other title (tio): ", $row->{tio}), #  alternate title
    preftag("N1", "WAVES tiu: ", $row->{tiu}),
    preftag("SN", "ISBN ", $row->{isbn}), #  - ISSN/ISBN (e.g. ISSN XXXX-XXXX)
    preftag("SN", "ISSN ", $row->{issn}), #  - ISSN/ISBN (e.g. ISSN XXXX-XXXX)
    tag("PB", $row->{corp}), #  - Publisher
    tag("CY", $row->{publ}), #  - City of Publication
    preftag("N1", "conference: ", $row->{conf}),
    preftag("N1", "edition: ", $row->{edtn}),
    preftag("N1", "WAVES sc: ", $row->{sc}),
    preftag("N1", "responsible: ", $row->{resp}),  # verbatim authors or something
    preftag("N1", "WAVES nd: ", $row->{nd}),
    preftag("N1", "number: ", $row->{nu}),
# Procite joins both N2 values into one giant paragraph.
# Even separating the tags from each other, or putting extra newlines in, doesn't help.
    tag("N2", $row->{abstract}), #  - Abstract
    tag("N2", $row->{res}),  # Resume (french abstract).
    preftag("N1", "lang: ", $row->{la}), # language.
    "";

#    tag("KW", $row->{de}), #  - Keywords (each keyword must be on separate line preceded KW -) # and include subj and species
    foreach my $list ($row->{de}, $row->{subj}, $row->{species}){
	print RIS map( tag("KW", $_), split(/\s*;\s*/, $list) );
    }

    print RIS "ER  - \n"; # end record tag

#    foreach my $col (@$names){     # DEBUGGING.
#	print RIS tag($col, $row->{$col});
#   }

    print RIS "\n\n";
}  #end of loop over CSV records

if(!$csv->eof){
    my ($cde, $str, $pos) = $csv->error_diag();
    my $badline = $csv->error_input;
#    $csv->error_diag();
#    print STDERR "\n\n";

#error code: $cde.
    my $start;
    $start = $pos - 6  if $pos-6 > 0;
    die "CSV reading failed on input line:\n", $badline,
    "\nproblem is: $str.  at character position $pos in line $. of input file:\n$ARGV\n",
    "position $pos is in the middle of: ", substr($badline, $start, 18), "\n",
    "\nMaybe this file was loaded/saved with Excel with incorrect CSV settings?\n",
    "WAVES and this program use: separator = ,  quote char = \"  escape char = \\ \n";
}
