# Parse Tab delimeted metadata files

package Metadata::Parser::Tab;
use strict;

use IO::File;

use lib '/app/tools/common/lib';
use Common::Log;
use Common::RSApp;
use Common::Assert;
use Data::Dumper;

use base qw( Metadata::Parser );

use constant DATE_FORMAT => 'yyyy-mm-dd';

sub _init {
    my ( $self, %args ) = @_;

    $self->SUPER::_init(%args);

    Common::Log::Debug("   Initializing Metadata::Parser::Excel Object");

    return $self;
}

sub open {
    my ( $class, %args ) = @_;
    my $self = bless {}, $class;
    $self->_init(%args);
    my $fh = new IO::File;
    my @result;

    Common::Log::Debug("Opening Tab Delimeted File: $self->{_infile}");

    eval {
        if ( $self->{_fh} ) {
            $fh = $self->{_fh};
        } else {
            $fh->open( $self->{_infile} ) || die "Failed to read from $self->{_infile}";
        }

        while ( my $row = <$fh> ) {
            chomp($row);
            push( @result, $row );
        }

        $self->{_row_count} = @result - 1;
        $self->{_file}      = \@result;
    };
    if ($@) {
        print STDERR "Failed to open file: $@\n";
        return undef;
    }

    return $self;
}

sub parse {
    my $self = shift;
    assert($self);

    $self->{_errors} = ();
    $self->{_data}   = undef;

    Common::Log::Debug("Parsing Tab File: $self->{_infile}");

    if ( $self->_validate_headers() ) {
        $self->_store_import_summary();
        $self->_import_data();
        $self->_store_import();
    }
    return $self->{_errors} ? undef : $self->{_data};
}

sub _validate_headers {
    my $self = shift;
    my $header;

    assert($self);
    assert( $self->{_file} );

    $header = ${ $self->{_file} }[0];

    my @cols = split( /\t/, $header ) if ($header);

    return $self->_validate_header_row(@cols);
}

sub _import_data {
    my $self = shift;
    my %column_indexes;
    my @headers;
    my $i    = 0;
    my $row  = 0;
    my $data = ();
    my @filters;
    my $col;

    assert($self);

    Common::Log::Debug("- Begin data conversion from tab file");

    # Add filter to trim whitespace from the front and back of a string.
    push( @filters, ( qr/\x0d/ => '' ) );
    push( @filters, ( qr/^\s*/ => '' ) );
    push( @filters, ( qr/\s*$/ => '' ) );
    push( @filters, ( qr/\s+/  => ' ' ) );

    @headers = split( /\t/, ${ $self->{_file} }[0] );

    Common::Log::Debug("   - Get column indexes");
    foreach $col (@headers) {

        # Trim spaces
        $col                = $self->_filter( $col, @filters );
        $col                = lc($col);
        $column_indexes{$i} = $col;
        $i++;
    }

    Common::Log::Debug("   - Reading row data");

    for ( $row = 1 ; $row < @{ $self->{_file} } ; $row++ ) {
        my $rowData = ${ $self->{_file} }[$row];

        next unless ( $rowData && length($rowData) );

        my @row = split( /\t/, $rowData );
        my $record = {};

        foreach $col ( keys(%column_indexes) ) {

            # Trim spaces
            my $celldata = $self->_filter( $row[$col], @filters );
            $record->{ $column_indexes{$col} } = $celldata;
        }

        $record->{'line-number'} = $row;

        push( @$data, $record );
    }

    $self->{_data} = $data;

    if ($data) {
        return 1;
    } else {
        my $errstr = "File contains no data";
        push( @{ $self->{_errors} }, $errstr );
        Common::Log::Print("ERROR: $errstr");

        return;
    }
}

1;
