#!/bin/env perl

=pod

=head1 NAME

make-conf - using data from parse-table, create Circos input files to visualize the table

=head1 SYNOPSIS
  
  cat parsed-table.txt | make-conf -dir data/
  
  # or
 
  make-conf -file table.txt -dir data/

=head1 DESCRIPTION

This script uses the output of parse-table to create Circos configuration files used to create circular table views as described here

 http://mkweb.bcgsc.ca/circos/tableviewer/

=head1 OUTPUT

Output files are placed in the directory defined by -dir parameter.

When drawing the image, make sure that the paths to data files defined in circos.conf point to where you've created the files.

=head1 CONFIGURATION

All configuration parameters are controlled by the configuration file - see etc/make-conf.conf.

=head1 HISTORY

=over

=item * 21 Jan 2009 v0.1

Versioned and updated.

=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-2008 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)
#                                                           2008
################################################################

use strict;
use Config::General;
use Data::Dumper;
use File::Basename;
use File::Path;
use FindBin;
use Getopt::Long;
use IO::File;
#use Math::VecStat qw(sum min max average);
#use Math::Round qw(round);
use Pod::Usage;
#use Set::IntSpan;
#use Statistics::Descriptive;
#use Storable;
#use Time::HiRes qw(gettimeofday tv_interval);
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,
	   "dir=s",
	   "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);
}

################################################################
# setup the input handle to be the file, if specified, otherwise
# read from STDIN
my $inputhandle;
if(my $file = $CONF{file}) {
  die "No such file $file" unless -e $file;
  open(F,$file);
  $inputhandle = \*FILE;
} else {
  printdebug("using STDIN");
  $inputhandle = \*STDIN;
}

my @rules = ({rx=>"colorpercentile",
	      file=>"colors_percentile.conf",
	      skip=>1},
	     {rx=>"chromosomes_scale",
	      file=>"scaling.conf",
	      skip=>0},
	     {rx=>"colordef",
	      file=>"colors.conf",
	      skip=>1},
	     {rx=>"karyo",
	      file=>"karyotype.txt",
	      skip=>1},
	     {rx=>"segmentlabel",
	      file=>"segmentlabel.txt",
	      skip=>1},
	     {rx=>"link cell",
	      file=>"cells.txt",
	      skip=>1},
	     {rx=>[qw(highlight \brow\b)],
	      file=>"row.txt",
	      skip=>2},
	     {rx=>[qw(colribboncap)],
	      file=>"cap.col.txt",
	      skip=>1},
	     {rx=>[qw(rowribboncap)],
	      file=>"cap.row.txt",
	      skip=>1},
	     {rx=>[qw(highlight \bcol\b)],
	      file=>"col.txt",
	      skip=>2},
	     {rx=>[qw(highlight \ball\b)],
	      file=>"all.txt",
	      skip=>2});

for my $rule (@rules) {
  unlink(sprintf("%s/%s",$CONF{dir},$rule->{file}));
}
LINE:
while(<$inputhandle>) {
  chomp;
  my $line = $_;
 RULE:
  for my $rule (@rules) {
    my $pass;
    if(ref($rule->{rx})) {
      $pass = grep($line =~ /$_/, @{$rule->{rx}}) == @{$rule->{rx}};
    } else {
      $pass = $line =~ $rule->{rx};
    }
    if($pass) {
      my $file = sprintf("%s/%s",$CONF{dir},$rule->{file});
      mkpath(dirname($file));
      open(F,">>$file") || die "cannot open file $file";
      my @tok = split(" ",$line);
      print F join(" ", @tok[$rule->{skip} .. @tok-1]),"\n";;
      close(F);
      printdebug("writing to $file",@tok);
    } else {
      next RULE;
    }
  }
}

sub validateconfiguration {
}

################################################################
#
# *** 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 ($ENV{LOGNAME} && -e "/home/$ENV{LOGNAME}/.$scriptname.conf" && -f _ && -r _) {
    $file = "/home/$ENV{LOGNAME}/.$scriptname.conf";
  } elsif (-e "$FindBin::RealBin/$scriptname.conf" && -f _ && -r _) {
    $file = "$FindBin::RealBin/$scriptname.conf";
  } elsif (-e "$FindBin::RealBin/etc/$scriptname.conf" && -f _ && -r _) {
    $file = "$FindBin::RealBin/etc/$scriptname.conf";
  } elsif (-e "$FindBin::RealBin/../etc/$scriptname.conf" && -f _ && -r _) {
    $file = "$FindBin::RealBin/../etc/$scriptname.conf";
  } else {
    return undef;
  }
  $OPT{configfile} = $file;

  my $conf;
  eval {
    $conf = new Config::General(-ConfigFile=>$file,
				-AllowMultiOptions=>"yes",
				-LowerCaseNames=>1,
				-AutoTrue=>1);
  };
  if($@) {
    printinfo($@);
    exit;
  }
  %CONF = $conf->getall;
}

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

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

sub printdumper {
  printinfo(Dumper(@_));
}

