#!/usr/bin/env perl

=pod

=head1 NAME

make_tutorial_images - create a batch file to run Circos for each tutorial

=head1 SYNOPSIS

  # create batch file with commands to create images
  > make_tutorial_images [-conf ../etc/make_tutorial_images.conf] > batchfile.sh
  # run the batch file (might take a while)
  > . batchfile.sh

=head1 DESCRIPTION

All parmaeters are defined through the configuration file in ../etc/make_tutorial_images.conf.

Use this script to create some, or all, tutorial images from the
tutorial configuration files. The tutorials are found in

  circos-x.xx/tutorials

and are split into sections and subsections. Each section deals with a
specific topic and each subsection contains a tutorial that
illustrates functionality.

For example tutorial 4.6 discusses formatting tick marks and its configuration file is

  circos-x.xx/tutorials/4/6/circos.conf

=head1 OUTPUT

All output files will be created in the directory specified by output_dir. 

=head1 HISTORY

=over

=item * 30 Sep 2008

Started.

=back 

=head1 BUGS

=head1 AUTHOR

Martin Krzywinski

=head1 CONTACT

  Martin Krzywinski
  Genome Sciences Centre
  Vancouver BC Canada
  www.bcgsc.ca
  martink@bcgsc.ca

=cut

################################################################
#
# Copyright 2002-2006 Martin Krzywinski
#
# This file is part of the Genome Sciences Centre Perl code base.
#
# This script is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This script is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this script; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
################################################################

################################################################
#                           Martin Krzywinski (martink@bcgsc.ca)
#                                                           2006
################################################################

use strict;
use Config::General;
use Data::Dumper;
use File::Basename;
use FindBin;
use Getopt::Long;
use IO::File;
use IO::Dir;
use Pod::Usage;
use Set::IntSpan;
use lib "$FindBin::RealBin";
use lib "$FindBin::RealBin/../lib";
use lib "$FindBin::RealBin/lib";
use vars qw(%OPT %CONF);

################################################################
#
# *** YOUR MODULE IMPORTS HERE
#
################################################################

GetOptions(\%OPT,
	   "bin=s",
	   "tutorial_root=s",
	   "output_dir=s",
	   "output_png",
	   "output_svg",
	   "output_redirect",
	   "configfile=s","help","man","debug+");

pod2usage() if $OPT{help};
pod2usage(-verbose=>2) if $OPT{man};
loadconfiguration($OPT{configfile});
populateconfiguration(); # copy command line options to config hash
validateconfiguration(); 
if($CONF{debug} > 1) {
  $Data::Dumper::Pad = "debug parameters";
  $Data::Dumper::Indent = 1;
  $Data::Dumper::Quotekeys = 0;
  $Data::Dumper::Terse = 1;
  print Dumper(\%CONF);
}

opendir(D,$CONF{tutorial_root});
while(my $item = readdir(D)) {
  next if $item eq "." || $item eq "..";
  my $dir = "$CONF{tutorial_root}/$item";
  process_dir($dir) if -d $dir;
}
close(D);

sub process_dir {
  my $dir = shift;
  my $dh = IO::Dir->new($dir);
  while(my $item = $dh->read) {
    next if $item eq "." || $item eq "..";
    if(-d "$dir/$item" && -e "$dir/$item/circos.conf") {
	make_command("$dir/$item");
    }
  }
  $dh->close();
}

sub make_command {
  my $dir = shift;
  my $outputfile;
  my ($tn,$ts) = (0,0);
  if($dir =~ /(\d+)\/(\d+)/) {
    ($tn,$ts) = ($1,$2);
    $outputfile = sprintf("tutorial-%02d-%02d.png",$1,$2);
  } else {
    die "could not make sense of tutorial directory $dir";
  }
  if($CONF{sections} && $CONF{sections} ne "all") {
    my $set = Set::IntSpan->new($CONF{sections});
    return if ! $set->member($tn);
  }
  if($CONF{sections_skip}) {
    my $set = Set::IntSpan->new($CONF{sections_skip});
    return if $set->member($tn);
  }
  if($CONF{subsections} && $CONF{subsections} ne "all") {
    my $set = Set::IntSpan->new($CONF{subsections});
    return if ! $set->member($ts);
  }
  if($CONF{subsections_skip}) {
    my $set = Set::IntSpan->new($CONF{subsections_skip});
    return if $set->member($ts);
  }
  my $redirect;
  if($CONF{output_redirect}) {
    ($redirect = $outputfile) =~ s/png$/txt/;
  } else {
    $redirect = "/dev/null";
  }
  my $command = sprintf("%s -conf %s/circos.conf -outputdir %s -outputfile %s %s &> %s/%s",
			$CONF{bin},
			$dir,
			$CONF{output_dir},
			$outputfile,
			$CONF{parameters},
			$CONF{output_dir},
			$redirect);
  printinfo("echo now making image $tn.$ts");
  printinfo($command);
}

sub validateconfiguration {
  $CONF{parameters} .= " -png " if $CONF{output_png};
  $CONF{parameters} .= " -svg " if $CONF{output_svg};
}

################################################################
#
# *** DO NOT EDIT BELOW THIS LINE ***
#
################################################################

sub populateconfiguration {
  foreach my $key (keys %OPT) {
    $CONF{$key} = $OPT{$key};
  }

  # any configuration fields of the form __XXX__ are parsed and replaced with eval(XXX). The configuration
  # can therefore depend on itself.
  #
  # flag = 10
  # note = __2*$CONF{flag}__ # would become 2*10 = 20

  for my $key (keys %CONF) {
    my $value = $CONF{$key};
    while($value =~ /__([^_].+?)__/g) {
      my $source = "__" . $1 . "__";
      my $target = eval $1;
      $value =~ s/\Q$source\E/$target/g;
      #printinfo($source,$target,$value);
    }
    $CONF{$key} = $value;
  }

}

sub loadconfiguration {
  my $file = shift;
  my ($scriptname) = fileparse($0);
  if(-e $file && -r _) {
    # great the file exists
  } elsif (-e "/home/$ENV{LOGNAME}/.$scriptname.conf" && -r _) {
    $file = "/home/$ENV{LOGNAME}/.$scriptname.conf";
  } elsif (-e "$FindBin::RealBin/$scriptname.conf" && -r _) {
    $file = "$FindBin::RealBin/$scriptname.conf";
  } elsif (-e "$FindBin::RealBin/etc/$scriptname.conf" && -r _) {
    $file = "$FindBin::RealBin/etc/$scriptname.conf";
  } elsif (-e "$FindBin::RealBin/../etc/$scriptname.conf" && -r _) {
    $file = "$FindBin::RealBin/../etc/$scriptname.conf";
  } else {
    return undef;
  }
  $OPT{configfile} = $file;
  my $conf = new Config::General(-ConfigFile=>$file,
				 -AllowMultiOptions=>"yes",
				 -LowerCaseNames=>1,
				 -AutoTrue=>1);
  %CONF = $conf->getall;
}

sub printdebug {
  printinfo("debug",@_)  if $CONF{debug};
}

sub printinfo {
  printf("%s\n",join(" ",@_));
}

