#!/usr/bin/perl

# Copyright 2013, Naoki Takebayashi <ntakebayashi@alaska.edu>
#
# This program 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 3 of the
# License, or (at your option) any later version.
#
# This program 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 program. If not, see <http://www.gnu.org/licenses/>.

# Version: 20130612

my $usage = "\nUsage: $0 [-5dfhnl] [-o outgroup] [inputfile] [outputfile]\n" .
    "  -l: landscape output\n" .
    "  -o integer: Use the i-th sequence as the outgroup (default=1)\n" .
    "  -n: run neighbor-joining\n" .
    "  -d: By default distance matrix is deleted, if you want to keep all\n".
    "      output files from running neighbor joinning, use this option\n".
    "  -f: inputfile is fasta instead of phylip format\n".
    "  -5: Version of phylip is 3.5xx (default: use 3.6xx)\n" .
    "This program creates the postscrpit tree file\n\n".
    "Without -n, input is phylip tree file\n".
    "With -n, input is phylip sequence data file\n\n".
    "Without any arguments, it assumes the inputfile name is 'outtree'.\n" .
    "If 1 argument is given, it is used as inputfile\n" .
    "If 2 arguments are given, 1st argument is inputfile name, 2nd argument\n".
    " is outputfilename.\n" .
    "Without the 2nd argument, default output filename is 'outtree.ps'\n";

use File::Copy;
use IO::File;
use POSIX qw(tmpnam);
use Getopt::Std;

my $fasta2phyBin = "fasta2phylip.pl";

getopts('hfno:l5') || die $usage;

die "$usage" if (defined($opt_h));

my $phylipVersion = "3.6";
if (defined($opt_5)) {
    $phylipVersion = "3.5";
}


if (@ARGV == 0) {
    $infile = "outtree\n";
    $outfile = "tree.ps";
} elsif (@ARGV == 1) {
    $infile = shift;
    $outfile = "tree.ps";
} elsif (@ARGV ==2) {
    ($infile, $outfile) = @ARGV;
} else {
    die "ERROR: give input and outputfile names\n";
}

if (defined($opt_n)) {
    if (defined($opt_f)) {  # convert fasta to phylip
	do {$tmpFile = tmpnam()} until $tmpFilefh = 
	    IO::File->new($tmpFile, O_RDWR|O_CREAT|O_EXCL);
	END {                   # delete the temp file when done
	    if (defined($tmpFile) && -e $tmpFile) {
		unlink($tmpFile) || die "Couldn't unlink $tmpFile : $!"
	    }
	};
	system ("$fasta2phyBin $infile > $tmpFile");
	$infile = $tmpFile;
    }
    RunNJ($infile);

    if (! defined ($opt_d)) {
	unlink("dist", "outfile");
    }
    $infile = "outtree\n";
}

if (defined($opt_l)) {
    if ($phylipVersion eq "3.6") {
	$landscape="h\n" ; 
    } elsif ($phylipVersion = "3.5") {
	$landscape="" ;      # with phylip 3.573c
    }
} else {
    if ($phylipVersion eq "3.6") {
	$landscape="" ;    # with older drawgram
    } elsif ($phylipVersion eq "3.5") {
	$landscape="1\n" ;       # with phylip 3.573c
    }
}

if ($phylipVersion  eq "3.6") {
    $option= $infile . $landscape .
"v
n
y
";
} elsif ($phylipVersion eq "3.5") {
# with phylip 3.573c
    $option= 
"l
n
2
P
4
90
"  . $landscape .
"
y
";
}

buFile("plotfile");

open (DRAW, "|drawgram") || die "Can't find drawgram\n";

print DRAW $option;
close(DRAW);

buFile($outfile);
move ("plotfile", $outfile) || die "Can't rename plotfile to $outfile";

exit(0);

sub RunNJ {
    my $infile = shift;

    if ($infile eq "outtree") {
	die "Need an inputfile";
    }
    
    buFile("outfile");
    my $option = "$infile\ny\n";
    open (DIST, "|dnadist") || die "Can't find dnadist\n";
    print DIST $option;
    close(DIST);
    
    buFile("dist");
    move("outfile", "dist");
    
    buFile("outtree");
    if(defined($opt_o)) {
	$og = "o\n" . $opt_o . "\n";
    } else {
	$og = "";
    }

    $option = "dist\n$og" . "y\n";

    open (NJ, "|neighbor") || die "Can't find dnadist\n";
    print NJ $option;
    close(NJ);

    return;
}

sub buFile {
    my $file = shift;
    if (-e $file) {
	move ("$file", "$file.old") || die "Can't move $file to $file.old\n";
    }
    return;
}
