#!/usr/bin/perl

use lib '/opt/local/lib/perl5/site_perl/5.8.9';
use XML::Smart;
use XML::XSLT;
use File::Random qw/:all/;

#global config vars
my $dir = "/Users/username/Recipes/Dinner-Validated/";
my $xsl = "/Users/username/Recipes/display_recipe_text.xsl";
my $DEBUG = 0; #set to 1 to print out debug information

#get our time for the filename to write to
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = localtime(time());
$mon++;
$mon = sprintf("%02d",$mon);
$mday= sprintf("%02d",$mday);
$year += 1900;

#create empty recipe book
my @recipebook;
my @meals;
my %used_recipe_ids;

#hash for ingredients
my %ingredients;

#load up initial preferences
my $pref_xml = XML::Smart->new("preferences.xml");
my $cust_id = $pref_xml->{preferences}[0]{customerid}[0];
my $custfile = "$cust_id-$mon$mday$year";

sub recipe_includes{
  my $ingredient = shift;
  my $file = shift;
  open(MYINPUTFILE, "<$file");
  my(@lines) = <MYINPUTFILE>;
  close MYINPUTFILE;
  my @fooditemlines = grep(/<fooditem>/,@lines);
  @fooditemlines = grep(!/optional/,@fooditemlines);
  my $count = grep(/$ingredient/,@fooditemlines);
  if($count > 0){
    return 1;
  }
  return 0;
}

sub preferences_block{
  my $block_count = shift;
  #begin specific to each preference
  my @excluded = $pref_xml->{preferences}[0]{preferencesblock}[$block_count]{exclude}{item}('@');
  my @required = $pref_xml->{preferences}[0]{preferencesblock}[$block_count]{required}{item}('@');
  my @wouldlike = $pref_xml->{preferences}[0]{preferencesblock}[$block_count]{wouldlike}{item}('@');
  my $no_of_meals = $pref_xml->{preferences}[0]{preferencesblock}[$block_count]{meals}[0];
  my @sorted_recipes;
  my %hashed_recipebook;
  
  
  #build the recipe book
  my @files = <$dir/*.xml>;
  foreach $file (@files){
      my $file_xml = XML::Smart->new($file);
      if ($DEBUG) {print "Considering $file\n";}

      #exclude if we've chosen it already
      next if exists($used_recipe_ids{$file_xml->{recipe}[0]{id}});
  
      my $pass = 1; #assume it passes 
      foreach $exclude (@excluded){
        ($req_type,$param) = split(/:/,$exclude);
        if($req_type eq 'ingredient'){
          if(recipe_includes($param,$file)){ 
            $pass = 0; 
            last;
          }
        }
      }
      next if !$pass; #if we found an ingredient that should be excluded, go to the next recipe
  
      $pass = 1;
      $prep_time = $file_xml->{recipe}[0]{recipeinfo}[0]{preptime}[0];
      $cook_time = $file_xml->{recipe}[0]{recipeinfo}[0]{cooktime}[0];
      $crockpot = $file_xml->{recipe}[0]{recipeinfo}[0]{crockpot}[0];
      foreach $require (@required){
        ($req_type,$param) = split(/:/,$require);
        if($req_type eq 'time'){
          if(($prep_time+$cook_time) > $param){ $pass = 0; }
        }elsif($req_type eq 'cooktime'){
          if($cook_time > $param){ $pass = 0; }
        }elsif($req_type eq 'preptime'){
          if($prep_time > $param){ $pass = 0; }
        }elsif($req_type eq 'crockpot'){
          if($crockpot ne $param){ $pass = 0; }
        }elsif($req_type eq 'ingredient'){
          if(!recipe_includes($param,$file)){ $pass = 0; }
        }
        last if !$pass; #stop if a recipe has failed any requirement
      } 
      next if !$pass; #if we failed any requirement, go to the next recipe
  
      push(@recipebook,$file);
      $hashed_recipebook{$file} = rand();
  
      foreach $like (@wouldlike){
        ($req_type,$param) = split(/:/,$like);
        if($req_type eq 'time'){
          if(($prep_time+$cook_time) <= $param){ $hashed_recipebook{$file}++; }
        }elsif($req_type eq 'cooktime'){
          if($cook_time <= $param){ $hashed_recipebook{$file}++; }
        }elsif($req_type eq 'preptime'){
          if($prep_time <= $param){ $hashed_recipebook{$file}++; }
        }elsif($req_type eq 'crockpot'){
          if($crockpot eq $param){ $hashed_recipebook{$file}++; }
        }elsif($req_type eq 'ingredient'){
          if(recipe_includes($param,$file)){ $hashed_recipebook{$file}++; }
        }
      } 
  }
  
  #order the recipes by the random number
  #@sorted_recipes = sort { $hashed_recipebook{$a} cmp $hashed_recipebook{$b} } keys %hashed_recipebook; 
  foreach $value (reverse sort {$hashed_recipebook{$a} cmp $hashed_recipebook{$b} } keys %hashed_recipebook)
  {
      push(@sorted_recipes,$value);
      print "$value $hashed_recipebook{$value}<br />\n";
  }
  
  if($no_of_meals > scalar @sorted_recipes){ 
    print "Too few candidate recipes\n";
    exit;
  }
  
  for($m = 0; $m < $no_of_meals; $m++){

    #choose a recipe
    #$random_recipe = random_file(-dir => $dir,-check => qr/[.]*\.xml/);
    #my $xml = XML::Smart->new($dir.$random_recipe);
    $random_recipe = $sorted_recipes[$m];
    my $xml = XML::Smart->new($random_recipe);

    #add recipe to list
    push(@meals,$random_recipe);
    $used_recipe_ids{$xml->{recipe}[0]{id}} = $xml->{recipe}[0]{title}; 

    my $i=0;
    while($xml->{recipe}[0]{ingredientlist}[0]{ingredient}[$i]{fooditem}[0] ne ''){
      $food_quantity = $xml ->{recipe}[0]{ingredientlist}[0]{ingredient}[$i]{quantity}[0];
      $food_unit = $xml->{recipe}[0]{ingredientlist}[0]{ingredient}[$i]{unit}[0];
      $food_item = $xml->{recipe}[0]{ingredientlist}[0]{ingredient}[$i]{fooditem}[0];
  
      if($food_unit eq 'ounce'){
        $food_unit = "ounces";
      }elsif($food_unit eq 'tablespoon'){
        $food_unit = "tablespoons";
      }elsif($food_unit eq 'teaspoon'){
        $food_unit = "teaspoons";
      }elsif($food_unit eq 'cup'){
        $food_unit = "cups";
      }elsif($food_unit eq 'clove'){
        $food_unit = "cloves";
      }elsif($food_unit eq 'fillet'){
        $food_unit = "fillets";
      }
  
      if (exists $ingredients{"$food_unit $food_item"}){
        $ingredients{"$food_unit $food_item"} += $food_quantity;
      }else{
        $ingredients{"$food_unit $food_item"} = $food_quantity;
      }
      $i++;
    }
  }
}


#iterate through the preference blocks
my $j=0;
while($pref_xml->{preferences}[0]{preferencesblock}[$j]{meals} ne ''){
  preferences_block($j,$pref_xml);
  $j++;
}

open (CUSTFILE, ">$custfile.txt");
  
#print titles of recipes chosen
print CUSTFILE "List of meals for the week:\n";
foreach $meal (@meals) {
  my $xml = XML::Smart->new($meal);
  my $title = $xml->{recipe}[0]{title};
  my $blurb = $xml->{recipe}[0]{recipeinfo}[0]{blurb}[0];
  if($blurb eq ''){
    print CUSTFILE "$title\n";
  }else{
    print CUSTFILE "$title:  $blurb\n";
  }
}
  
print CUSTFILE "\n";
  
#print alphabetical list of ingredients
print CUSTFILE "Ingredient list:\n";
foreach $key (sort (keys(%ingredients))) {
   print CUSTFILE "$ingredients{$key} $key\n";
}
  
#print recipes chosen
foreach $meal (@meals) {
  # create an instance of XSL::XSLT processor
  my $xslt = XML::XSLT->new ($xsl);
  
  # transform XML file and print output
  print CUSTFILE $xslt->serve($meal);
    
  # free up some memory
  $xslt->dispose(); 
}
  
close(CUSTFILE);

