package ARDB::TemplateProcessing;

use strict;

sub new 
 { 
  my $class     = shift;
  my $types_ref = shift;
 
  my @types = split ',', $types_ref;
  
  my $self = 
   {
    'types'      => {},
    'attributes' => [],
    'tables'     => [],
   };  

  foreach ( @types )
   {
    $self -> {types} -> {$_} = 1;
   }

    
  bless $self, $class;
    
  return $self;
    
 }

sub add_record_type
 {
  my $self = shift;

  foreach ( @_ )
   {
    $self -> { types } -> {$_} = 1;
   }
 }

sub add_attribute
 {
  my $self = shift;

  foreach ( @_ )
   {
    push @{ $self -> {attributes} }, $_;
   }

 }

sub add_table
 {
  my $self       = shift;
  my $table_name = shift;

  push @{ $self -> {tables} }, { name => $table_name } ;
 }

sub add_table_mapping
 {
  my $self       = shift;
  my $table_name = shift;
  my $mapping    = shift;

  foreach ( @{ $self -> {tables} } )
   {
    if ( $_ -> {name} eq $table_name )
     {
      $_ -> {map} = $mapping;
     }
   }

 }



sub add_actions
 {
  my $self   = shift;
#  my $actions = shift;
 
  
  while ( scalar @_ )
   {
    my $key    = shift;
    my $value  = shift;
    push ( @{ $self -> {actions} } , 
      { type    => $key, content => $value } );
   }
 }

sub find_matching_values
 {
  my $self     = shift;
  my $template = shift;

  my @values ;
  
  # check if template's type matches with our conditions 
  # and boil out otherwise
  my $ttype = $template->{'template-type'}[0];
  if( not $self->{template_types_hash}->{$ttype} ) { return (); }

  # now check all of the attribute specifications, remembering all 
  # the matches on the way

  foreach ( @{ $self -> {attributes}} ) 
   {
   	my @path_sections;
    if ( @path_sections = split /\// )
     {

      # we have a template tree.  it has several levels.  If we look at it from 
      # the point of view of roots, first level will be where we have handle 
      # and template-type attributes;  
      #
      # first we find matching branches of the first level.
      #
      # then we cut those branches, and take a closer look at them.
      # I mean we check if those branches have next-level branches or the leaves 
      # which match the specification.


      # $current will hold an arrayref to the branches we study 
      my $current = [ $template ];

      # this will step through all the attribute specification parts,
      # e.g. if attr spec is 'author/handle', this will go through ['author','handle']
      # e.g. if attr spec is 'author/workplace/handle', this will go 
      # through ['author', 'workplace', 'handle']

      foreach my $path_section ( @path_sections ) 
       {
       	 my @deep = ();

         foreach my $array_item ( @$current )
           {
             my $cur_array = $array_item -> {$path_section};
             if( defined $cur_array ) {
                push @deep,   @$cur_array;
             }   
           }
         $current = [ @deep ];
       }
      push @values, @$current;
     
     }
    else
     {
      if ( $template -> {$_} )
       {
        push @values, @{ $template -> {$_} };
       }
     }
   }


  # return the found

  return @values;
 }

#

sub get_actions_for_template
 {
  my $self     = shift;
  my $template = shift;

  my @values = $self -> find_matching_values ( $template );
  
  foreach my $value ( @values ) { 

      foreach ( @{ $self->{actions } } ) 
      { 
	  if( $_ -> {type} eq 'relation' ) 
	  {
	      my $handle = $template -> {handle} -> [0];

	      if ( $_ -> {content} -> {forward} )
               {
	        my $action = new ARDB::Action::Relation( $handle, 
						    $_ -> {content} -> {forward}, 
						    $value, 
						    $handle ); 
	       }
	      elsif ( $_ -> {content} -> {backward} )
	       {
	        my $action = new ARDB::Action::Relation( $value, 
						    $_ -> {content} -> {backward}, 
						    $handle, 
						    $handle ); 
	       }
	  }
      }
  }

 }



1;
