#------------------------------------------------------------
# Copyright (C) 2009 RoyaltyShare, Inc.   All Rights Reserved
#------------------------------------------------------------

package Metadata::Translator;

#
# Translator
#
# Translate meteadata import files into a common format that
# the importer class understands.
#
# Usage:
#
#   my $translator = new Metadata::Translator( filename => $file );
#   my $data = $parser->parse();
#
#   parse will return an object containing
#

use strict;

use Data::Dumper;

use lib '/app/tools/common/lib';
use Common::Assert;

use lib '/app/tools/metadata/lib';
use Metadata::Parser;

use base 'Common::Translator';

sub _versionClasses {
    qw( Metadata::Translator::Version::v5xml
      Metadata::Translator::Version::v1
      Metadata::Translator::Version::v2
      Metadata::Translator::Version::v5 );
}
sub _defaultVersionClass { 'Metadata::Translator::Version::v6' }

sub _mapItem {
    my $self    = shift;
    my $value   = shift;
    my $column  = shift;
    my $line    = $self->{_parser}->currentRow;
    my $version = $self->{_version};
    my $map     = $version->getMapByColumn($column);
    my @maps    = ref( $map->{to} ) eq 'ARRAY' ? @{ $map->{to} } : ( $map->{to} );
    my @items;

    my $itemClass = $self->_itemClass();

    foreach my $to (@maps) {
        my $item = $itemClass->new(
            value       => $value,
            key         => $to,
            originalKey => $map->{from},
            line        => $line,
            column      => $column
        );

        push( @items, $item );
    }

    return \@items;
}

sub _mapItemFromXML {
    my $self    = shift;
    my $value   = shift;
    my $path    = shift;
    my $line    = $self->{_parser}->currentRow;
    my $version = $self->{_version};
    my @items;

    my $itemClass = $self->_itemClass();

    my $map = $version->getMapByColumn($path);
    my @maps = ref( $map->{to} ) eq 'ARRAY' ? @{ $map->{to} } : ( $map->{to} );

    foreach my $to (@maps) {
        if ( ref($to) ) { $to = $to->{column}; }
        assert( $to, "column attribute required" );

        my $transformed = $version->transform( $path, $to, $value );
        my $item = $itemClass->new(
            value       => $transformed,
            key         => $to,
            originalKey => $path,
            line        => $line
        );

        push( @items, $item );
    }

    return \@items;
}

sub _map {
    my $self = shift;

    if ( $self->{_parser}->fileType() eq 'xml' ) {
        return $self->_mapXML(@_);
    } else {
        return $self->_mapTable(@_);
    }

}

sub _mapXML {
    my $self        = shift;
    my $row         = shift;
    my $recordClass = $self->_recordClass();
    my $line        = $self->{_parser}->currentRow;
    my $record      = $recordClass->new( line => $line );
    my $item;
    my $version = $self->{_version};

    assert( $row, "Row required" );

    my $paths = $version->getAllXpaths;

    foreach my $path (@$paths) {
        Common::Log::Debug("  -> Search xpath: $path");
        my $value = $row->getColumn($path);

        my $item = $self->_mapItemFromXML( $value, $path );

        foreach my $i ( @{$item} ) {
            $record->addItem($i);
        }
    }

    return $record;
}

sub _mapTable {
    my $self         = shift;
    my $row          = shift;
    my $record       = $self->SUPER::_map($row);
    my $dependancies = $self->version->_dependantColumns();
    my $keyItem;
    my $dependantItem;

    return $record unless $dependancies;

    foreach my $key ( keys(%$dependancies) ) {
        $keyItem = $record->getItemByKey($key);

        unless ( $keyItem && $keyItem->value() ) {
            foreach my $item ( @{ $dependancies->{$key} } ) {
                $dependantItem = $record->getItemByKey($item);
                $dependantItem->{_value} = undef;
            }
        }
    }

    return $record;
}

sub _getParser {
    my $self = shift;
    Metadata::Parser->Parse(@_);
}

###
1;    # Play nicely.
###
