#!/usr/bin/perl
use strict;
use warnings;

package Uploader;

use Getopt::Long;

use lib qw(Core);
use lib qw(Classes);

use TaskConfiguration;
use LocalTaskConfiguration;

use TasksManager;

sub new {
    my ($class) = @_;
    
    my $self = {
        _target => '',
        _model1_name => '',
        _model2_name => '',
        _plugin => '',
        _models_dir => '',
        _targets_dir => '',
        _results_dir => '',
        _result_extension => '',
	_param => '',
	_casp_version => $LOCAL_CONFIG->{CASP_VERSION}
	
    };
    
    bless $self, $class;
    return $self;
}

sub usage {
    my ($self) = @_;
    
    printf("Usage ./upload_task.pl:\n");
    printf("\t--target:               target\n");
    printf("\t--model1:               model1 name (Required). For example: T0387.pdb\n");
    printf("\t--model2:               model2 name or '*' for all models from models dir. For example: T0283TS004_1 or *\n");
    printf("\t--plugin:               plugin name (Required). For example: lga_sda_4, lga_sia_5, mvsm, mammoth, etc...\n");
    printf("\t--targets_dir:          custom targets dir. Current: %s\n", $LOCAL_CONFIG->{TARGETS_DIR});
    printf("\t--models_dir:           custom models dir. Current: %s/T0XXX\n", $LOCAL_CONFIG->{MODELS_DIR});
    printf("\t--results_dir:          results directories. (Required). Use single quotes ' if you planning use ; for separed directories.\n");
    printf("\t--param:                Additional param.\n");
    printf("\t                        Example: '/shared/prediction_4/workspace/RESULTS/CASP8/4A/DATA/T0387/;/shared/prediction_4/workspace/RESULTS/CASP8/4A/ROTATED/T0387/;/shared/prediction_4/workspace/RESULTS/CASP8/4A/ALIGNMENT/T0387/'\n", );
    printf("\t--result_extension:     results file extension. No extension by default. Example: lga\n\n");
    printf("Example1: upload_tasks.pl --target=T0387 --model1=T0387.pdb --model2=* --plugin=lga_sda_4 --results='/shared/prediction_4/workspace/RESULTS/CASP8/4A/DATA/T0387/;/shared/prediction_4/workspace/RESULTS/CASP8/4A/ROTATED/T0387/;/shared/prediction_4/workspace/RESULTS/CASP8/4A/ALIGNMENT/T0387/' --result_extension=lga\n\n");
    printf("Example2: upload_tasks.pl --target=T0387 --model1=T0387.pdb --model2=* --plugin=lga_sia_5 --results='/shared/prediction_5/workspace/RESULTS/CASP8/5A/DATA/T0387/;/shared/prediction_5/workspace/RESULTS/CASP8/5A/ROTATED/T0387/;/shared/prediction_5/workspace/RESULTS/CASP8/5A/ALIGNMENT/T0387/' --result_extension=lga\n\n");
    printf("\n");
    exit();
}

my $target_name = "T0000";

sub read_parameters {
    my ($self) = @_;
    
    my $isparams = GetOptions(
        "target=s"   => \$self->{_target},
        "model1=s"   => \$self->{_model1_name},
        "model2:s"   => \$self->{_model2_name},
        "plugin=s"   => \$self->{_plugin},
    	"models_dir=s"   => \$self->{_models_dir},
        "targets_dir=s"   => \$self->{_targets_dir},
        "results_dir=s"   => \$self->{_results_dir},
        "result_extension=s"   => \$self->{_result_extension},
	"param=s" => \$self->{_param},
    );
    
    if((!defined($self->{_model1_name}) || ($self->{_model1_name} eq '')) ||
       (!defined($self->{_plugin}) || ($self->{_plugin} eq '')) ||
       (!defined($self->{_target}) || ($self->{_target} eq '')) ||
       (!defined($self->{_results_dir}) || ($self->{_results_dir} eq ''))) {
        printf("ERROR! Missing required parameters\n");
        $self->usage();
    }
        # truncate .pdb in target file name
        $target_name = $self->{_model1_name};
        $target_name =~ s/.pdb//;    
    
    if(!defined($self->{_targets_dir}) || ($self->{_targets_dir} eq '')) {
        $self->{_targets_dir} = $LOCAL_CONFIG->{TARGETS_DIR};
    }
    
    if(!defined($self->{_models_dir}) || ($self->{_models_dir} eq '')) {
        $self->{_models_dir} = sprintf("%s/%s", $LOCAL_CONFIG->{MODELS_DIR}, $target_name);
    }

  
}

sub upload_tasks {
    my ($self) = @_;
    
    my $model1_file = sprintf("%s/%s", $self->{_targets_dir}, $self->{_model1_name});
    
    if("mvsm_serv" ne $self->{_plugin} && "molprb_serv" ne $self->{_plugin}){
    	if(! -e $model1_file ) {
        	printf("ERROR! File doesn't exist: %s\n", $model1_file);
	        exit();
	    }
    }

    if(("mvsm" eq $self->{_plugin} || "mvsm_serv" eq $self->{_plugin} || "rr_conts" eq $self->{_plugin} || "molprb_serv" eq $self->{_plugin}) && ($self->{_target} !~ m/^T[0-9]{4}/)){
		printf("WARNING! We don't run neither mvsm nor rr_conts for assistance guided targets and refinement targets.\nTarget: %s; plugin: %s\n", $self->{_target}, $self->{_plugin});
		exit();
    }

    my @models = ();
	if ($self->{_model2_name} eq '*') {
        @models = $self->get_models();
	} elsif ($self->{_model2_name}) {
        my $model2_file = sprintf("%s/%s", $self->{_models_dir}, $self->{_model2_name});
        
        if(! -e $model2_file) {
            printf("ERROR! File doesn't exist: %s\n", $model2_file);
            exit();
        }
        
        push(@models, $self->{_model2_name}); #$model2_file
	} else {
        push(@models, '');
    }
    
    my $models_count = scalar(@models);
    
    if($models_count == 0) {
        printf("ERROR! No model2 files were found at %s\n", $self->{_models_dir});
        exit();
    }
    
    my $task_manager = new TasksManager();
	my %p = (target => $self->{_target}, plugin => $self->{_plugin});
	$p{model2_file} = $self->{_model2_name}
		unless ($models_count > 1);
	if($self->{_plugin} eq "rr_conts"){
		$p{param} = $self->{_param};
	}
	$task_manager->delete_by(%p);

	if ('mvsm' eq $self->{_plugin} ){ #|| 'mvsm_serv' eq $self->{_plugin}) {
		my @all = $self->get_models();
		my $all_count = scalar(@all);
		for my $y (@models) {
			my $models_x = '';
			for my $x ($self->get_models()) {
				#next unless $x gt $y;
				next if $x eq $y; # BM
				if ($models_x eq '') {
					$models_x = $x;
				} else {
					$models_x = sprintf("%s\/%s", $models_x, $x);
				}
			}
#			printf("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t",$self->{_target}, $self->{_plugin}, '', $self->{_models_dir}, $models_x, $self->{_models_dir}, $y, $self->{_results_dir}, $y) ;
			$task_manager->add($self->{_target}, $self->{_plugin}, '', $self->{_models_dir}, $models_x, $self->{_models_dir}, $y, $self->{_results_dir}, $y);
		}
	
	} elsif('mvsm_serv' eq $self->{_plugin}){
                my @all = $self->get_models();
                my $all_count = scalar(@all);
                for my $y (@models) {
                        my $models_x = '';
                        for my $x ($self->get_models()) {
                                next if $x ge $y;
                                # next if $x eq $y; # BM
                                if ($models_x eq '') {
                                        $models_x = $x;
                                } else {
                                        $models_x = sprintf("%s\/%s", $models_x, $x);
                                }
                        }
#                       printf("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t",$self->{_target}, $self->{_plugin}, '', $self->{_models_dir}, $models_x, $self->{_models_dir}, $y, $self->{_results_dir}, $y) ;
			if($models_x ne ''){
	                        $task_manager->add($self->{_target}, $self->{_plugin}, '', $self->{_models_dir}, $models_x, $self->{_models_dir}, $y, $self->{_results_dir}, $y);
			}
                }
	
	} else {
		for(my $i = 0; $i < $models_count; $i++) {
			my $result_name = $models[$i];
			if (defined($self->{_result_extension}) && ($self->{_result_extension} ne '')) {
				$result_name = sprintf("%s.%s", $models[$i], $self->{_result_extension});
			}
			if (defined($self->{_result_extension}) && ($self->{_result_extension} ne '') && ($self->{_plugin} =~ m/molprb/)) {
				$result_name = sprintf("%s.%s",$self->{_target}, $self->{_result_extension});
			}
#                        printf("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t\n",$self->{_target}, $self->{_plugin}, '', $self->{_targets_dir}, $self->{_model1_name}, $self->{_models_dir}, $models[$i], $self->{_results_dir}, $result_name, $self->{_param}) ;
			$task_manager->add($self->{_target}, $self->{_plugin}, '', $self->{_targets_dir}, $self->{_model1_name}, $self->{_models_dir}, $models[$i], $self->{_results_dir}, $result_name, $self->{_param});
		}
	}
}

sub get_models {
    my ($self) = @_;
    
    my @models = ();
    if(open(MODELS, sprintf("ls -1 %s/ |", $self->{_models_dir}))) {
        while(<MODELS>) {
            chomp;
            push(@models, $_);
        }
        close(MODELS);
    }
    
    return @models;
}

sub run() {
    my ($self) = @_;
    
    $self->read_parameters();
    
    $self->upload_tasks();
}

my $uploader = new Uploader();
$uploader->run();
