# Copyright (C) 2005  Joshua Hoblitt
#
# $Id: Parser.pm,v 1.4 2005-10-14 23:31:39 jhoblitt Exp $

package PS::IPP::PSFTP::Parser;

use strict;

use Carp qw( carp );
use Params::Validate qw( validate_pos SCALAR );

use vars qw( @FIELDS @REQUIRED_FIELDS );

@FIELDS = qw( date time file_id type attributes size md5 url );
@REQUIRED_FIELDS = qw( date time file_id type size md5 url );

sub new
{
    my $class = shift;

    validate_pos(@_);

    my $self = bless {}, ref ($class) || $class;

    return $self;
}

sub parse
{
    my $self = shift;

    my ($doc) = validate_pos(@_,
        {
            type    => SCALAR,
            regex   => qr/\S+/, # string with atleast 1 non WS char
        }
    );

    # pack data into an HoH
    my @data;
    foreach my $line (split /\n/, $doc) {
        # convert string to an array of lines
        my %record;
        @record{@FIELDS} = map { $_ ? $_ : undef } split /\|/, $line;

        # check for the proper number of fields (null or not)
        unless (scalar keys %record == scalar @FIELDS) {
            carp "record: $line does not have the proper number of fields\n";
            return undef;
        }

        # check that all required fields are defined
        foreach my $key (@REQUIRED_FIELDS) {
           unless (defined $record{$key}) {
                carp "record: $line is missing required field: $key\n";
                return undef;
           }
        }

        # convert attributes into a hash
        if (defined $record{attributes}) {
            my @pairs = split /:/, $record{attributes};
            
            my %attr;
            foreach my $pair (@pairs) {
                my ($key, $value) = split /=/, $pair;

                unless (defined $key) {
                    carp "record: $line has an attribute: $pair "
                       . " with no key";
                    return undef;
                }

                unless (defined $value) {
                    carp "record: $line has an attribute: $pair"
                       . " with no value";
                    return undef;
                }

                # pack pairs into a hash
                $attr{$key} = $value;
            }
        
            # replace attributes string with a hashref
            if (%attr) {
                $record{attributes} = \%attr;
            } else {
                delete $record{attributes};
            }
        }

        # pack date & time into stamp
        $record{stamp} = $record{date} . "T" . $record{time};
        delete $record{date};
        delete $record{time};

        my $obj = bless \%record, "PS::IPP::PSFTP::Record";

        # pack as a FIFO
        unshift @data, $obj;
    }

    return @data ? \@data : undef;
}

package PS::IPP::PSFTP::Record;

use base qw( Class::Accessor::Fast );

use vars qw( @FIELDS );

@FIELDS = qw( stamp file_id type attributes size md5 url );

__PACKAGE__->mk_accessors( @FIELDS );

1;

__END__
