/* ----------------------------------------------------------------------
 * Randseq -- program for generating random sequences
 * Copyright (C) 2000 January Weiner III
 * 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 2
 * 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, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
 * USA.
 ---------------------------------------------------------------------- */

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <time.h>

#include "genpak.h"
#include "gp_getopt.h"

#define PROGNAME "gp_randseq"
#define VERSION "0.4"
#define DEFAULT_SEQUENCE_LENGTH 100

sekw* GenerateRandomSequence(sekw *tmpl,long dlug, int seql) ;
sekw* TakeSeqPart(sekw *insek, long start,long end) ;

/*
 *
 */



int main(int argc, char *argv[])
{
	extern int optind ;
	extern char *optarg ;
	int width = 70 ; /* width with which the sequence gets formatted */
	FILE *in, *out ;
	sekw *Rezultat,*rseq ;
	long dlugosc ;
	int numseq = 1,dseqlen = DEFAULT_SEQUENCE_LENGTH ;

	int i,c;
	char message[100] ;
	int errflg = 0 ;

	allwarnings = NULL ;

	progname = argv[0] ;

	while ((c = gp_getopt(argc, argv, "mn:l:vhHqd")) != EOF)
		switch(c) {
		case 'l':
			if(sscanf(optarg,"%i",&dseqlen) != 1) {
				gp_warn("Could not read argument for option -l") ;
			} else {
				sprintf(message,"Random sequence length set to %i",dseqlen) ;
				gp_warn(message) ;
			}
			break ;
		case 'n':
			if(sscanf(optarg,"%i",&numseq) != 1) {
				gp_warn("Could not read argument for option -n") ;
			} else {
				sprintf(message,"Number of sequences set to %i",numseq) ;
				gp_warn(message) ;
			}
			break ;
		case 'm':
			gp_error("Sorry, this option is not ready-to-use yet :-(") ;
			break ;
		case 'q':
			quiet = TRUE ;
			break ;
		case 'v':
			fprintf(stderr,"%s version %s\n",progname,VERSION) ;
			exit(0) ;
			break ;
		case 'H':
			html = TRUE ;
			break ;
		case 'd':
			debug = TRUE ;
			gp_warn("Running in debug mode") ;
			break ;
		case 'h':
			Help() ;
			break ;
		default:
			errflg++ ;
			break;
		}

	if(errflg) {
			sprintf(message,"Type '%s -h' for help",progname) ;
			gp_error(message) ;
	}


	/* open the file pointer to read the sequences 
 	 * from: standard input or a file provided? */


	if(optind >= argc) {
		in = stdin ;
		if(debug) gp_warn("Reading from stdin") ;
	} else {
		in = gp_file_open(argv[optind],"r") ;
		if(debug) gp_warn("Opened file for reading") ;
	}


/* opening the file pointer to write the output: 
 * standard output or file provided? */
	optind++ ;

	if(optind >= argc) out = stdout ;
	else gp_file_open(argv[optind],"wb") ;
	

	srand((unsigned) time(NULL));

	if((Rezultat = gp_seq_read_fragment(in,0,0,0)) == NULL)
		gp_error("Could not read input file") ;
	dlugosc = strlen(Rezultat->sequ) ;

	if(debug) gp_warn("Sequence read") ;

	for(i = 0;i<numseq;i++) {
		rseq = GenerateRandomSequence(Rezultat,dlugosc,dseqlen) ;
		gp_seq_print_fasta(out,rseq,width) ;
		free(rseq) ;
	}
	
	if(html) gp_warn_print_all(out) ;
	fclose(out) ;
	fclose(in) ;
	return(0);
}

/* this procedure generates random sequences cut out from the sequence
 * tmpl. Random sequences have the length seql, and tmpl is supposed to
 * have the length dlug. */

sekw* GenerateRandomSequence(sekw *tmpl, long dlug, int seql) {

	int dir ;
	long rstart, rend, rlen ;
	sekw* rseq ;

	/* Reserve space for random sequence */

	rlen = dlug-seql ;
	
	rstart = (long) ((double)rand()/((double)RAND_MAX + 1)*rlen) ;
	dir = (int) ((double)rand()/((double)RAND_MAX + 1)*2) ;
	rend = rstart+seql ;

	rseq = TakeSeqPart(tmpl,rstart,rend) ;

	if(debug) fprintf(stderr,"From %li to %li, %i rev\n", 
		rstart,rend,dir) ;
		
	rseq->name = gp_strdup("Random Sequence") ;
	rseq->type = DNA ;

	if(dir) rseq = gp_seq_reverse(rseq) ;


	return rseq ;


}

/* This sequence cuts out a fragment from sequence *insek, from parameter
 * start to parameter end. This parameters must be checked, because the
 * procedure itself does not check them. Neither the sequence is reversed
 * if start>end. */

sekw* TakeSeqPart(sekw *insek, long start,long end) {
	sekw *outseq ;
	long i,seql,t ;


	if(start>end) {
		t = start; start = end; end = t;
	}

	seql = end-start;
	
	outseq = (sekw*) malloc(sizeof(sekw));
	outseq->sequ = (char*) malloc(sizeof(char)*(seql+1)) ;
	
	for(i = 0;i<seql;i++) {
		outseq->sequ[i] = insek->sequ[(i+start)] ;
	}
	outseq->sequ[seql] = '\0' ;

	return(outseq) ;

}

void Help()
{
printf("\n");
printf("%s version %s - generating random sequences",PROGNAME,VERSION);
printf("\n");
printf("  Usage:\n");
printf("     %s [options] [ input file ] [ output file ]\n",progname);
printf("\n");
printf("  Options:\n");
printf("     -l _val_ : set random sequence length to _val_\n");
printf("     -n _num_ : set the number of generated sequences to _num_\n");
printf("     -q       : run in quiet mode\n");
printf("     -v       : print version information & exit\n");
printf("     -h       : print this help screen & exit\n");
printf("     -H       : output in HTML\n");
printf("     -d       : turn on debugging\n\n");
exit(0);
}


			
