#!/bin/bash

function random_position {
# $1 is string to give a position on
 sequence=$1; size=${#sequence}
 echo -e $((1 + RANDOM % $size))
}

function generate_sequence {
# max length of sequence to be generated is $1
# min length of sequence to be generated is $2
 length=$(shuf -i $2-$1 -n 1)
 echo -e "$(cat /dev/urandom | tr -dc 'ACGT' | head -c $length)"
}

function off_by {
# number chars to change is $1
# sequence is $2
  COUNTER=$1; sequence=$2;
 while [  $COUNTER -gt 0 ]; do
  sequence=$( echo $sequence | sed "s/./$( cat /dev/urandom | tr -dc 'ACGT' | head -c 1)/$( random_position $sequence)" )
  COUNTER=$(($COUNTER-1))
 done
 echo -e "$sequence"
}

function generate_cluster {
# $1 is number of sequnces wanted
# $2 is max size of sequnces wanted
# $3 is min size of sequences wanted
# $4 how many maximum potential differences each sequence should have
# $5 how many maximum potential differences each sequence should have
# $6 is bool for outputting ref sequences
COUNTER=$1; BASE_SEQ=$( generate_sequence $2 $3 ); DIF=$4; dif=$5; ref=$6
 if [ $ref != "false" ]; then echo $BASE_SEQ >> $ref; fi
 while [ $COUNTER -gt 0 ]; do
    #echo "$1 $2 $3 $4 $5 $6" >> test_1 ;
  number_of_difs=$(shuf -i $dif-$DIF -n 1)
  echo -e "$( off_by $number_of_difs $BASE_SEQ )"
  COUNTER=$(($COUNTER-1))
 done
}

function generate_master_list {
# $1 how many different OTUS
# $2 sequences per OTU
# $3 max size of sequences
# $4 min size of sequences
# $5 max differences in those sequences
# $6 min differences amoung OTU sequences
 COUNTER=$1; PER=$2; MAXSIZE=$3; MINSIZE=$4; DIF=$5 dif=$6 ref=$7
     #echo "$1 $2 $3 $4 $5 $6" >> test_2 ;
 while [ $COUNTER -gt 0 ]; do
  if [ $ref != "false" ]; then echo ">REF-$COUNTER" >> $ref; fi
  echo -e "$( generate_cluster $PER $MAXSIZE $MINSIZE $DIF $dif $ref)"
  COUNTER=$(($COUNTER-1))
 done
}


function generate_fastas {
# $1 is number of fasta
# $2 is total number of OTUS
# $3 is number of sequences per OTU
# $4 is max number of OTUs in each file
# $5 is max length of seqneuces
# $6 is max differences amoung OTU sequences
# $7 is the project name
# $8 is min number of sequnces in each file
# $9 is min length of seqneuces
# $10 is min differences amoung OTU sequences
# $11 is reuse OTU document
 COUNTER=$1; OTUS=$2; PER=$3; NUM=$4; SIZE=$5; DIF=$6; PROJ=$7; num=$8; size=$9; dif=${10}; reu=${11} save=${12} add=${13} only=${14} ref=${15}
 
 if [ $reu == "false" ]; then
  echo "Building master OTU list"
  MASTER_LIST=$( generate_master_list $OTUS $PER $SIZE $size $DIF $dif $ref)
 else
	 MASTER_LIST=$( for seq in $(cat $reu); do echo $seq; done )
 fi

 if [ $only == "false" ]; then
  while [ $COUNTER -ge 1 ]; do
   echo "WORKING ON FASTA $COUNTER"
   number_of_seqs=$(shuf -i $num-$NUM -n 1)
   sequences=$( echo -e "$MASTER_LIST" | shuf -n $number_of_seqs )
   counter=1
   for seq in $sequences; do
    #echo "Sequence: $PROJ-$COUNTER-$counter$add"
    echo ">FASTA-"$COUNTER"_"$counter$add >> $PROJ-$COUNTER.fasta
    echo $seq >> $PROJ-$COUNTER.fasta
    counter=$(($counter+1))
   done
   COUNTER=$(($COUNTER-1))
  done
 fi

 if [ $save != "false" ]; then 
  echo -e $MASTER_LIST >> $save
 fi
}

# getopts
OPTS=`getopt -o f:o:s:W:L:D:w:l:d:p:r:R:S:a:Oh --long num-fasta:,total-otus:,number-of-seq-per-otu:,max-number-otus-per-file:,max-length-of-sequences:,max-injected-differences-in-otus:,min-number-otus-per-file:,min-length-of-sequences:,min-injected-differences-in-otus:,project-name:,reuse:,gen-ref:,save:,add:,only,help -n 'parse-options' -- "$@"`

if [ $? != 0 ] ; then echo "Failed parsing options." >&2 ; exit 1 ; fi

echo "$OPTS"
eval set -- "$OPTS"

num_fasta=1
total_otus=1
number_of_seq_per_otu=1
number_otus_per_file=1
length_of_sequences=100
injected_differences_in_otus=0
project_name="default"
reuse="false"
save="false"
add="-run"
only="false"
ref="false"

while true; do
  case "$1" in
  -f | --num-fasta ) num_fasta="$2"; shift 2;;
  -o | --total-otus ) total_otus="$2"; shift 2;;
  -s | --number-of-seq-per-otu ) number_of_seq_per_otu="$2"; shift 2;;
  -W | --max-number-otus-per-file ) number_otus_per_file="$2"; shift 2;;
  -L | --max-length-of-sequences ) length_of_sequences="$2"; shift 2;;
  -D | --max-injected-differences-in-otus ) injected_differences_in_otus="$2"; shift 2;;
  -w | --min-number-otus-per-file ) min_number_otus_per_file="$2"; shift 2;;
  -l | --min-length-of-sequences ) min_length_of_sequences="$2"; shift 2;;
  -d | --min-injected-differences-in-otus ) min_injected_differences_in_otus="$2"; shift 2;;
  -p | --project-name ) project_name="$2"; shift 2;;
  -r | --reuse ) reuse="$2"; shift 2;;
  -R | --gen-ref ) ref="$2"; shift 2;;
  -S | --save ) save="$2"; shift 2;;
  -a | --add ) add="$2"; shift 2;;
  -O | --only ) only="true"; shift;;
  -h | --help ) help=true; shift;;
  -- ) shift; break ;;
  * ) break ;;
  esac
done
shift $((OPTIND -1))

if [ $help ]; then
 echo "-f or --num-fasta, Number of Fasta files to be generated"
 echo "-o or --total-otus, Total number of OTUs to be generated"
 echo "-s or --number-of-seq-per-otu, Number of sequences per otu"
 echo "-W or --max-number-otus-per-file, Maximum Number of sequences per file"
 echo "-L or --max-length-of-sequences, Maximum Length of sequences"
 echo "-D or --max-injected-differences-in-otus, Maximum Number of injected differences per-sequence per-OTU"
 echo "-w or --min-number-otus-per-file, Maximum Number of sequnces per file"
 echo "-l or --min-length-of-sequences, Maximum Length of sequences"
 echo "-d or --min-injected-differences-in-otus, Maximum Number of injected differences per-sequence per-OTU"
 echo "-p or --project-name, Project name"
 echo "-r or --reuse, Reuse OTU, given a file of OTUS, one per line, use them to make new files"
 echo "-R or --gen-ref, generate a reference fasta"
 echo "-S or --save, Save OTUs into file"
 echo "-a or --add, add a bit of string to the generated sequnces"
 echo "-O or --only, only make OTUs, don't bother making fasta files"
 exit 1
fi

echo "Number of Fasta files to be generated: $num_fasta"
echo "Total number of OTUs to be generated: $total_otus"
echo "Number of sequences per otu: $number_of_seq_per_otu"
echo "Min number of OTUs per file: $min_number_otus_per_file, Max number of sequnces per file: $number_otus_per_file"
echo "Min length of sequences: $min_length_of_sequences, Max length of sequences: $length_of_sequences"
echo "Min number of injected differences per-sequence per-OTU: $min_injected_differences_in_otus, Max injected differences in otus: $injected_differences_in_otus"
echo "Project name: $project_name"
echo "Reuse is: $reuse"
echo "Save is: $save"
echo "Add is: $add"
echo "Only OTU Generation is: $only"
echo "Call is: generate_fastas $num_fasta $total_otus $number_of_seq_per_otu $number_otus_per_file $length_of_sequences $injected_differences_in_otus $project_name $min_number_otus_per_file $min_length_of_sequences $min_injected_differences_in_otus $reuse $save $add $only $ref"

generate_fastas "$num_fasta" "$total_otus" "$number_of_seq_per_otu" "$number_otus_per_file" "$length_of_sequences" "$injected_differences_in_otus" "$project_name" "$min_number_otus_per_file" "$min_length_of_sequences" "$min_injected_differences_in_otus" "$reuse" "$save" "$add" "$only" "$ref"

exit 1;
