#!/usr/bin/perl -w

# generates the models required to run a given model over a range of parameter values. Also
# create graph metadata if required and runs the simulations. If a given PATTERN has fewer
# values than others then it will keep the last value for future simulations.

use strict;
use File::Basename;

my @colours = ('#ff0000','#0000ff','#008000','#808000','#800080',
               '#008080','#800000','#000080','#ff00ff');
my $simulator = "$ENV{HOME}/sf.net/CellMLSimulator/build/release/CellMLSimulator";
my $modelsHome = "$ENV{HOME}/cellml/models";
my $pwd = dirname($0);

if (scalar @ARGV < 6) {
  die "usage: $0 <model template> <graph template> <output directory> <graph format> <landscape|portrait> <PATTERN=value1,value2,...,valueN> [PATTERN=value1,value2,...,valueN] ...\n";
}

my $template = shift;
my $graphTemplate = shift;
my $dir = shift;
if (! -d $dir) {
  die "Output directory does not exist ($dir)\n";
}
my $format = shift;

my $orientation = shift;
if ($orientation =~ /port/i) {$simulator .= " --portrait";}

my $modelFNT = "model_%05d.xml";
my $nameT = "%05d";

# The parameter substitutions
my %subs;
foreach my $a (@ARGV) {
  my ($key,$value) = split /=/,$a;
  my @values = split /,/,$value;
  $subs{$key} = \@values;
}
# sort out the value ranges - make all the arrays the same length, repeating the last entry
# as required
my $N = 0;
foreach my $k (keys %subs) {
  if (scalar @{$subs{$k}} > $N) { $N = scalar @{$subs{$k}}; }
}
foreach my $k (keys %subs) {
  my $n = scalar @{$subs{$k}};
  if ($n < $N) {
    foreach my $i ($n .. $N-1) {
      push @{$subs{$k}},$subs{$k}->[$n-1];
    }
  }
}
#foreach my $k (keys %subs) {
#  print "key: $k\n";
#  print "values: @{$subs{$k}}\n";
#}

# first make all the required CellML models
for (my $i=0;$i<$N;$i++) {
  my $file = sprintf("$dir/$modelFNT",$i);
  my $name = sprintf($nameT,$i);
  open(CELLML,">$file") or die "Unable to open CellML model file ($file): $!\n";
  open(TEMPLATE,"<$template") or die "Unable to open model template file ($template): $!\n";
  while (<TEMPLATE>) {
    # special ones?
    s/NAME/$name/g;
    s/MODELS_HOME/$modelsHome/g;
    s/PWD/$pwd/g;
    foreach my $k (keys %subs) {
      #print "$k -> $subs{$k}->[$i] ";
      s/$k/$subs{$k}->[$i]/g;
    }
    print CELLML $_;
  }
  close TEMPLATE;
  close CELLML;
}

# and now generate the graph metadata
open(TEMPLATE,"<$graphTemplate") or die "Unable to open the graph template ($graphTemplate): $!\n";
open(GRAPH,">$dir/graphs.xml") or die "Unable to open the output graph ($dir/graphs.xml): $!\n";
while (<TEMPLATE>) {
  if (/<!--\s+REPEAT\s+START\s+-->/) {
    # grab everything between REPAET START and REPEAT END
    my $rS = $_;
    while (<TEMPLATE>) {
      $rS .= $_;
      if (/<!--\s+REPEAT\s+END\s+-->/) { last; }
    }
    # do the string replacements N times
    my $cI = 0;
    for (my $i=0;$i<$N;$i++) {
      my $str = $rS;
      my $file = sprintf($modelFNT,$i);
      my $name = sprintf($nameT,$i);
      $str =~ s/NAME/$name/g;
      $str =~ s/MODEL_FILE/$file/g;
      $str =~ s/MODELS_HOME/$modelsHome/g;
      $str =~ s/PWD/$pwd/g;
      foreach my $k (keys %subs) {
        #print "$k -> $subs{$k}->[$i] ";
        $str =~ s/$k/$subs{$k}->[$i]/g;
      }
      # set the line colour
      if ($cI >= @colours) {$cI = 0;}
      $str =~ s/COLOUR/$colours[$cI]/g;
      $cI++;
      print GRAPH $str;
    }
  } else {
    print GRAPH $_;
  }
}
close GRAPH;
close TEMPLATE;

# now we can run the simulations
my $command = "$simulator --data=$dir/data.h5 --graph-directory=$dir --graph-format=$format $dir/graphs.xml > $dir/CellMLSimulator.log";
system($command);

exit;