#! /bin/sh
#!perl -w # --*- Perl -*--
eval 'exec perl -x $0 ${1+"$@"}'
    if 0;
#------------------------------------------------------------------------------
#$Author: antanas $
#$Revision: 7416 $
#$URL: svn://www.crystallography.net/cod-tools/tags/v2.7/scripts/cif_printout $
#$Date: 2019-11-15 19:15:35 +0200 (Fri, 15 Nov 2019) $
#$Id: cif_printout 7416 2019-11-15 17:15:35Z antanas $
#------------------------------------------------------------------------------
#*
#* Parse CIF file and print out the structure generated by CIF parser.
#*
#* USAGE:
#*    $0 --options input1.cif input*.cif
#**

use strict;
use warnings;
use COD::CIF::JSON qw( cif2json json2cif );
use COD::CIF::Parser qw( parse_cif );
use COD::SOptions qw( getOptions );
use COD::SUsage qw( usage options );
use COD::ShowStruct qw( showRef );
use COD::ErrorHandler qw( process_errors
                          process_parser_messages
                          report_message );
use COD::ToolsVersion;
use Data::Dumper;

my $die_on_error_level = {
    ERROR   => 0,
    WARNING => 0,
    NOTE    => 0
};

my $output_format = 'dump';
my $input_json  = 0;
my %options = ( no_print => 1 );

#*  OPTIONS:
#*   --input-cif,
#*   --input-json
#*                     Specify the format of input file(s). Default CIF.
#*
#*   --output-dump
#*                     Output parsed CIF file in internal dump format (default).
#*
#*   --output-json
#*                     Output generated structure in JSON.
#*
#*   --output-struct
#*                     Output generated structure using COD::ShowStruct module.
#*                     This option is deprecated and will be removed in
#*                     future releases.
#*
#*   --json
#*                     Set both input and output formats to JSON.
#*
#*   --use-perl-parser
#*                     Use Perl parser for CIF parsing.
#*
#*   --use-c-parser
#*                     Use Perl & C parser for CIF parsing.
#*
#*   --help, --usage
#*                     Output a short usage message (this message) and exit.
#*   --version
#*                     Output version information and exit.
#**
@ARGV = getOptions(
    "--do-not-unprefix-text" => sub{ $options{do_not_unprefix_text} = 1 },
    "--do-not-unfold-text"   => sub{ $options{do_not_unfold_text} = 1 },
    "--fix-errors"           => sub{ $options{fix_errors} = 1 },
    "--fix-duplicate-tags-with-same-values"  =>
        sub{ $options{fix_duplicate_tags_with_same_values} = 1 },
    "--fix-duplicate-tags-with-empty-values" =>
        sub{ $options{fix_duplicate_tags_with_empty_values} = 1 },
    "--fix-data-header"     => sub{ $options{fix_data_header} = 1 },
    "--fix-datablock-names" => sub{ $options{fix_datablock_names} = 1 },
    "--fix-string-quotes"   => sub{ $options{fix_string_quotes} = 1 },
    "--fix-missing-closing-double-quote" =>
        sub{ $options{fix_missing_closing_double_quote} = 1 },
    "--fix-missing-closing-single-quote" =>
        sub{ $options{fix_missing_closing_single_quote} = 1 },
    "--fix-ctrl-z"  => sub{ $options{fix_ctrl_z} = 1 },
    "--allow-uqstring-brackets" => sub{ $options{allow_uqstring_brackets} = 1 },

    # Bison parser is default:
    "--input-cif"  => sub { $options{parser} = 'c' },
    "--input-json" => sub { $options{parser} = 'json' },

    "--output-dump"   => sub { $output_format = 'dump' },
    "--output-json"   => sub { $output_format = 'json' },
    "--output-struct" => sub { $output_format = 'struct' },

    "--json" => sub { $options{parser} = 'json'; $output_format = 'json' },

    "--use-perl-parser" => sub { $options{parser} = 'perl' },
    "--use-c-parser"    => sub { $options{parser} = 'c' },
    "--options"         => sub { options; exit },
    "--help,--usage"    => sub { usage; exit },
    '--version'         => sub { print 'cod-tools version ',
                                 $COD::ToolsVersion::Version, "\n";
                                 exit }
);

if ( $output_format eq 'struct' ) {
    warn "$0:: WARNING, the 'struct' output format is considered " .
         "deprecated -- it will be removed in future releases.\n";
}

@ARGV = ( "-" ) unless @ARGV;

binmode STDOUT, ':encoding(UTF-8)';
binmode STDERR, ':encoding(UTF-8)';

foreach( @ARGV ) {

    my( $data, $err_count, $messages );
    if( $input_json ) {
        eval {
            open my $inp, '<' . $_ or die 'ERROR, '
              . 'could not open bibliography file for reading -- '
              . lcfirst($!) . "\n";
            $data = json2cif( join( "\n", <$inp> ) );
            close $inp or die 'ERROR, '
              . 'error while closing file after reading -- '
              . lcfirst($!) . "\n";
            $err_count = 0;
        };
        if ($@) {
            process_errors( {
              'program'  => $0,
              'filename' => $_,
              'message'  => $@
            }, 1 );
        }
    } else {
        $options{no_print} = 1;
        ($data, $err_count, $messages) = parse_cif( $_, \%options );
        process_parser_messages( $messages, $die_on_error_level );
    }
    
    foreach my $datablock ( @$data ) {
        if( $output_format eq 'json' ) {
            print cif2json( $datablock );
        } elsif( $output_format eq 'struct' ) {
            showRef( $datablock );
        } else {
            local $Data::Dumper::Varname = 'datablock';
            local $Data::Dumper::Sortkeys = 1;
            print Dumper( $datablock );
        }
    }

    report_message( {
        'program'   => $0,
        'filename'  => $_,
        'err_level' => 'NOTE',
        'message'   =>  "$err_count error(s) encountered while processing the file"
    }, $die_on_error_level->{'NOTE'} );
}
