#!/usr/bin/perl

use strict;
use warnings;

my @list = ();
my $n;
my $smin = 10;
my $smax = 10;
my @split = ();
my @concat = ();
my $randf = 1;
my $concatamer = "";
my $separator = "";
my $base;
my $arg;
my $input = "";
my $output = "";
my $routput = "";
my $separator_error_rate = 0;
my $bad_separators = 0;
my $prefix = "";
my $cut = 0;

my $version = 0.5;
my $vname = "ditags2concatamers.pl";

if (!$ARGV[0] || $ARGV[0] eq "-h") {
	print  "\n\t-smin <integer> \t:: define the minimum size (in # of ditags) of the concatamer to be generated [default=$smin]\n",
	"\t-smax <integer> \t:: define the maximum size (in # of ditags) of the concatamer to be generated [default=$smax]\n",
	"\t-e <0-100> \t\t:: define an error percentage in the CATG punctuation sites [default=$separator_error_rate]\n",
	"\t-f      \t\t:: create 5' and 3' end random sized sequences flanking the concatamer [default=FALSE]\n",
	"\t-n      \t\t:: prefix of the name of the concatamers [default=$prefix]\n",
	"\t-i <FILE> \t\t:: input file name \n",
	"\t-o <FILE> \t\t:: output file name \n",
	"\t-r <FILE> \t\t:: report output file name [default=STDERR]\n",
	"\t-h      \t\t:: display help information\n",
	"\t-v      \t\t:: display current version\n",
	"\n\t$vname Version $version\n\n";
	exit;
}               

if ($ARGV[0] eq "-v") {
	print ("\n\t$vname Version $version\n\n");
	exit;        
}      

#
#first read command line to collect arguments
#
while (my $arg = shift(@ARGV)) {
	#
	#size of the concatamer
	#
	if ($arg eq "-smin") {
		if ($arg = shift(@ARGV)) {
			$smin = $arg;
			if ($smin < 0) {
				print STDERR "ERROR: INVALID MINIMUM SIZE\n";
				exit;
			}
		}
		else {
			print STDERR "ERROR: INVALID MINIMUM SIZE\n";
			exit;
		}
	}
	#
	#random factor
	#
	elsif ($arg eq "-smax") {
		if ($arg = shift(@ARGV)) {
			$smax = $arg;
			if ($smax <= 0) {
				print STDERR "ERROR: INVALID MAXIMUM SIZE\n";
				exit;
			}
		}
		else {
			print STDERR "ERROR: INVALID MAXIMUM SIZE\n";
			exit;
		}
	}
	#
	#Ditag cut flag 
	#
	elsif ($arg eq "-f") {
		$cut = 1;
	}

	#
	#error rate
	#
	elsif ($arg eq "-e") {
		if ($arg = shift(@ARGV)) {
			$separator_error_rate = $arg;
			if ($separator_error_rate < 0 || $separator_error_rate > 100) {
				print STDERR "ERROR: ERROR RATE INVALID\n";
				exit;
			}
		}
		else {
			$separator_error_rate = 0;
		}
	}
	#
	#prefix name
	#
	elsif ($arg eq "-n") {
		if ($arg = shift(@ARGV)) {
			$prefix = $arg;
		}
	}

	#
	#output file
	#
	elsif ($arg eq "-o") {
		if ($arg = shift(@ARGV)) {
			$output = $arg;
		}
		else {
			print STDERR "ERROR: OUTPUT FILE NOT SPECIFIED\n";
			exit;
		}
	}

	#
	#input file
	#
	elsif ($arg eq "-i") {
		if ($arg = shift(@ARGV)) {
			$input = $arg;
		}
		else {
			print STDERR "ERROR: INPUT FILE NOT SPECIFIED\n";
			exit;
		}
	}
	#
	#report output file
	#
	elsif ($arg eq "-r") {
		if ($arg = shift(@ARGV)) {
			$routput = $arg;
		}
		else {
			print STDERR "ERROR: REPORT OUTPUT FILE NOT SPECIFIED\n";
			exit;
		}
	}
}


if ($input) {
	open INPUT, "<$input" or die "COULD NOT OPEN $input : $!";
	$input = "<INPUT>";
}
else {
	$input = "<>";
}

if ($output) {
	open OUTPUT, ">$output" or die "COULD NOT OPEN $output : $!";
}

if ($routput) {
	open ROUTPUT, ">$routput" or die "COULD NOT OPEN $routput : $!";
}

$randf = $smax - $smin + 1;

$n = $smin + int (rand ($randf));

my $pre = "";
my $pos = "";
my $conc_n = 0;
my $done = 0;
while (my $ditag = eval ($input)) {
	chomp ($ditag);
	$ditag = &clean ($ditag);
	if (!$ditag) {
		next;
	}
	$separator = &new_separator($separator_error_rate);
	if ($separator ne "catg") {
		&printerr ("*$separator$ditag\n");
	}

	if ($done == $n) {
		&printout (">$prefix$conc_n\n$concatamer$separator$pos\n");
		$concatamer = "";
		$n = $smin + int (rand ($randf));
		$done = 0;
	}
	if ($done == 0) {
		$conc_n++;
		if ($cut) {
			my $cutpoint = int (rand (length ($ditag)));
			$pos = substr ($ditag, 0, $cutpoint);
			$pre = substr ($ditag, $cutpoint);
			$concatamer .= $pre;
		}
		else {
			$concatamer .= $separator . $ditag;
		}
		$done++;
	}
	else {
		$concatamer .= $separator . $ditag;
		$done++;
	}
}

if ($concatamer) {
	&printout (">$prefix$conc_n\n$concatamer$separator$pos\n");
}


&printerr ("BAD SEPARATORS : $bad_separators \n");

close INPUT;
close OUTPUT;

sub new_separator {
	my $error_rate = shift;
	my $base;
	my @index2base = ("a", "c", "t", "g");
	my $position;

	if (rand(100) < $error_rate){
		$position = int(rand(4));
		$bad_separators ++;
		if ($position == 0){
			while (($base = $index2base[int(rand(4))]) eq "c"){};
			$separator = $base."atg";
		}
		elsif ($position == 1){
			while (($base = $index2base[int(rand(4))]) eq "a"){};
			$separator = "c".$base."tg";
		}
		elsif ($position == 2){
			while (($base = $index2base[int(rand(4))]) eq "t"){};
			$separator = "ca".$base."g";
		}
		else{
			while (($base = $index2base[int(rand(4))]) eq "g"){};
			$separator = "cat".$base;
		}


	}
	else {
		$separator = "catg";
	}

	return $separator;
}


sub printout {
	if ($output) {
		while (my $p = shift()) {
			print OUTPUT $p;
		}
	}
	else {
		while (my $p = shift()) {
			print $p;
		}
	}
}


sub printerr {
	if ($routput) {
		while (my $p = shift()) {
			print ROUTPUT $p;
		}
	}
	else {
		while (my $p = shift()) {
			print STDERR $p;
		}
	}
}

sub clean {
	my $string = shift;

	$string =~ s/^\s+//;
	$string =~ s/\s+$//;

	return $string;
}

