package Genome::Model::Tools::Music::Plot::MutationRelation;

use warnings;
use strict;
use Genome;
use IO::File;
use List::Util qw( sum );
use Carp;
use POSIX qw( WIFEXITED );

our $VERSION = $Genome::Model::Tools::Music::VERSION;

class Genome::Model::Tools::Music::Plot::MutationRelation {
    is => 'Command::V2',
    has_input => [
        input_matrix => { is => 'String', doc => "A gene/sample matrix generated by the mutation-relation tool" },
        output_pdf => { is => 'String', doc => "An output pdf file to draw the plot to" },
    ],
    has_optional_input => [
        skip_zero_mut_samples => { is => 'Boolean', doc => "Don't plot samples that have no mutations on any gene being plotted", default => 1 },
        genes_to_plot => { is => 'String', doc => "Comma-separated list of genes to plot (example: DNMT3A,NPM1)" },
        plot_genes_in_order_listed => { is => 'Boolean', doc => "Plot the genes in the order that they're listed. Default is to plot them in descending order by number of mutations", default => 0 },
    ],
    doc => "Makes plots for results from the mutation-relation tool",
};

sub help_detail {
    return <<HELP;
Given a matrix generated using "music mutation-relation --mutation-matrix-file", this
tool will generate a plot that highlights mutual exclusivity or concurrence between the mutation
status of a predefined set of genes.
HELP
}

#########################################################################

sub execute {
    my $self = shift;
    my $input_matrix = $self->input_matrix;
    my $output_pdf = $self->output_pdf;
    my $skip_zero_mut_samples = $self->skip_zero_mut_samples;
    my $genes_to_plot = $self->genes_to_plot;
    my $plot_genes_in_order_listed = $self->plot_genes_in_order_listed;

    # Load the gene names from the matrix
    my $headFh = IO::File->new( $input_matrix );
    my @cols = split( /\t/, $headFh->getline );
    # Create a hash of the gene names, which associates each with an R-friendly name
    my %genes_in_matrix = map{chomp; my $t = $_; s/\W/_/g; ( $t, $_ )} splice( @cols, 1 );
    $headFh->close;

    # Discard any user-specified genes that are not in the input matrix
    # being sure to preserve the order of the genes in the input

    if( defined $genes_to_plot ) {        
        my %genes = map{($_,1)} split( /,/, $genes_to_plot );
        foreach my $gene ( keys %genes ) {
            unless( defined $genes_in_matrix{$gene} ) {
                warn "Skipping gene $gene which is not seen in the provided input-matrix\n";
                delete $genes{$gene};
            }
        }
        #preserve the order of genes in the input
        my @glist = split(",",$genes_to_plot);
        my @finalList;
        foreach my $g (@glist){
            if(defined($genes{$g})){
                push(@finalList, $g)
            }
        }
        $genes_to_plot = join(",",@finalList);
    }


    # If user didn't specify genes-to-plot, then plot every gene in the input-matrix
    else {
        $genes_to_plot = join( ",", values %genes_in_matrix );
    }

    # Create a temporary mutation matrix with R-friendly gene names
    my $tmp_matrix = Genome::Sys->create_temp_file_path;
    ( $tmp_matrix ) or die "Couldn't create a temp file. $!";
    my $inFh = IO::File->new( $input_matrix );
    my $outFh = IO::File->new( $tmp_matrix, ">" );
    while( my $line = $inFh->getline ) {
        chomp( $line );
        my @cols = split( /\t/, $line );
        if( $line =~ m/^Sample\t/ ) { # Handle the header line
            $outFh->print( join( "\t", $cols[0], map{$genes_in_matrix{$_}}@cols[1..$#cols] ) . "\n" );
        }
        elsif( !$skip_zero_mut_samples || sum( @cols[1..$#cols] ) > 0 ) {
            $outFh->print( join( "\t", @cols ) . "\n" );
        }
    }
    $outFh->close;
    $inFh->close;

    # Call R to create a plot for the user-specified genes
    my $plot_cmd = "R --slave --args < " . __FILE__ . ".R $tmp_matrix $genes_to_plot $output_pdf $plot_genes_in_order_listed";
    WIFEXITED( system $plot_cmd ) or croak "Couldn't run: $plot_cmd ($?)";

    return 1;
}

1;
