#!/bin/env perl

=pod

=head1 NAME

colorinterpolate - generate color definitions of interpolated colors suitable for color.conf 

=head1 SYNOPSIS

  colorinterpolate -inspace rgb|hsv -calcspace rgb|hsv -start x1,y1,z1 -end x2,y2,z2 -steps 100

=head1 DESCRIPTION

=head2 SPACES

RGB values should range 0-255.

HSV values should be H=0-360, S=0-1, V=0-255.

=head1 HISTORY

=over

=item * 8 February 2010

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-2010 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)
#                                                           2010
################################################################

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

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

#memoize("get_num_links");

GetOptions(\%OPT,
	   "space=s",
	   "start=s",
	   "end=s",
	   "steps=i",
	   "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);
}

my @c1 = split(",",$CONF{start});
my @c2 = split(",",$CONF{end});

# convert start/end colors to RGB, if the input space is hsv
if($CONF{space} eq "hsv") {
  if($CONF{calcspace} eq "hsv") {
    # done
  } elsif ($CONF{calcspace} eq "rgb") {
    @c1    = hsv2rgb(@c1);
    @c2    = hsv2rgb(@c2);
  }
} elsif ($CONF{space} eq "rgb") {
  if($CONF{calcspace} eq "hsv") {
    @c1    = rgb2hsv(@c1);
    @c2    = rgb2hsv(@c2);
  } elsif ($CONF{calcspace} eq "rgb") {
    # done
  }
}

for my $i (0..$CONF{steps}) {
  my @c = (interpvalue($c1[0],$c2[0],$i,$CONF{steps}),
	   interpvalue($c1[1],$c2[1],$i,$CONF{steps}),
	   interpvalue($c1[2],$c2[2],$i,$CONF{steps}));
  if($CONF{calcspace} eq "hsv") {
    @c = hsv2rgb(@c);
  } elsif ($CONF{calcspace} eq "rgb") {
    # done
  }
  printinfo(sprintf("%s%03d = %d,%d,%d",$CONF{rootname},$i,@c));
}

sub interpvalue {
  my ($start,$end,$step,$steps) = @_;
  return $start + $step*($end-$start)/$steps;
}

sub rgb2hsv {
  my @c = @_;
  my $c = Graphics::ColorObject->new_RGB([@c]);
  my @nc = @{$c->as_HSV()};
  printinfo(@c,@nc);
  return @nc;
}
sub hsv2rgb {
  my @c = @_;
  my $c = Graphics::ColorObject->new_HSV([@c]);
  return @{$c->as_RGB()};
}

sub validateconfiguration {
  $CONF{space} ||= "rgb";
  $CONF{steps} ||= 100;
  $CONF{start} ||= "255,0,0";
  $CONF{end}   ||= "0,0,255";
}

################################################################
#
# *** 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(" ",@_));
}

