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

#include "mod.h"
#include "help.h"

extern struct mod_info M;
struct options opt, default_opt;

static char **av;              /* Local pointer to argv */
static int ac;                 /* Local copy of argc    */

static int nr_songs;           /* Nr of songs specified                */

static short songs[MAX_SONGS];      /* Starting pos in argv for the songs */
static char playedsongs[MAX_SONGS]; /* True if song has been played       */

static int cur_idx, songs_played;

int getarg(char **, int *);
void parse_options(int);

void init_options(int argc, char *argv[])
{
    int index;
    char next, tmp;
    char *s;
    
    av=argv;
    ac=argc;
    nr_songs=0;
    cur_idx=0;
    songs_played=0;
    
    bzero((void *)&default_opt, sizeof(struct options));
    bzero((void *)&playedsongs, MAX_SONGS*sizeof(char));

    index=1;

    while(index < ac) {
	while(index < ac) {
	    s=av[index];
	    if(*s == '-') {
		s++;
		next=0;
		while(*s && !next) {
		    switch(*s) {
		      case 'h':
			printf(HELP_TEXT, av[0]);
			exit(0);
		      case 'V':
			default_opt.showlines=1;
			default_opt.sync_output=1;
			break;
		      case 'v':
			default_opt.verbose++;
			break;
			
		      case 'L':
			default_opt.replay_forever=1;
			break;
		      case 'r':
			default_opt.random_mode=1;
			break;

		      case 'i':
			printf("Sorry, interactive mode not implemented yet"
			       "...\n");
			exit(0);
			break;

		      case 'N':
		      case 'o':
		      case 'O':
		      case 'P':
		      case '5':
		      case '6':
			break;
		      case 'a':
		      case 'c':
		      case 'l':
		      case 'm':
		      case 'p':
		      case 's':
		      case 't':
			tmp=*s;
			if(!getarg(&s, &index)) {
			    printf("%s: option -%c requires a numerical"
				   " argument\n", av[0], tmp);
			    exit(1);
			}
			next=1;
			break;
		      case 'f':
			getarg(&s, &index);
			next=1;
			break;
		      default:
			printf("%s: Unknown option -- %c\n", av[0], *s);
			exit(1);
		    }
		    s++;
		}
		index++;
	    }
	    else {
		songs[nr_songs++]=index;
		index++;
		break;
	    }
	}
    }

    if(!nr_songs) {
	printf(USAGE_TEXT, av[0], av[0]);
	exit(0);
    }

    default_opt.active_voices=-1; /* All voices active */
    default_opt.tempo=125;        /* PAL-tempo         */
    default_opt.speed=6;
    default_opt.click_removal=0;  /* No clickremoval by default */
    default_opt.low_note=0;       /* Let patternloader set these */
    default_opt.high_note=0;
    default_opt.maxtime=0;        /* No maxtime by default */

    opt=default_opt;
    parse_options(0); /* Get global options (filename=av[0] -> no problem) */
    default_opt=opt;
    
    /* One song can be looped forever w/o reloading it (if -L and !-l) */
    if(nr_songs == 1 && default_opt.replay_forever && !default_opt.loopcount)
	default_opt.loopcount=424711; /* Should be enough :-) */
    else
	default_opt.loopcount=1;      /* Play song once       */
    
    srand(time((time_t)0)); /* Randomize */
}


/* Sets *s to the start of the argument. Returns true if the first character
 * of the argument is a digit.
 */
int getarg(char **s, int *index)
{
    *s=*s+1;
    if(!**s) {
	*index=*index+1;
	if(*index >= ac) {
	    printf("%s: Missing argument for option "
		   "-- %c\n", av[0], *(*s-1));
	    exit(1);
	}
	*s=av[*index];
    }
    
    return (**s >= '0' && **s <= '9');
}


int get_next_module(void)
{
    int n, i;

    opt=default_opt;
    
    if(songs_played == nr_songs) {
	if(!opt.replay_forever)
	    return 0;
	
	bzero((void *)&playedsongs, MAX_SONGS*sizeof(char));
	songs_played=0;
	cur_idx=0;
    }

    if(opt.random_mode) {
	n=rand()%(nr_songs-songs_played);
	for(i=0; n>=0; ++i)
	    if(!playedsongs[i])
		--n;
	playedsongs[--i]=1;
	cur_idx=i;
    }

    parse_options(songs[cur_idx]); /* Parse options and set M.filename */
    songs_played++;
    cur_idx++;
    
    return 1;
}


void parse_options(int index)
{
    char next;
    char *s;

    strcpy(M.filename, av[index++]); /* Set filename */
    
    while(1) {
	s=av[index];
	if(*s == '-') {
	    s++;
	    next=0;
	    while(*s && !next) {
		switch(*s) {

		    /* These needs no further processing */

		  case 'h': case 'V': case 'v': case 'L': case 'r':
		  case 'i':
		    break;

		    /* These take no arguments */
		    
		  case 'N':
		    opt.ntsc_samples=1;
		    break;
		  case 'o':
		    opt.low_note=BASE_NOTE+1*12;
		    opt.high_note=BASE_NOTE+4*12-1;
		    break;
		  case 'O':
		    opt.low_note=BASE_NOTE+0*12;
		    opt.high_note=BASE_NOTE+5*12-1;
		    break;
		  case 'P':
		    opt.ntsc_samples=0;
		    break;
		  case '5':
		    opt.tempo=125; /* 50 Hz (125 BPM) -> 2.000/100 s */
		    opt.nobpm=1;
		    break;
		  case '6':
		    opt.tempo=150; /* 60 Hz (150 BPM) -> 1.667/100 s */
		    opt.nobpm=1;
		    break;
		    
		    /* These take arguments */
		    
		  case 'a':
		    getarg(&s, &index);
		    next=1;
		    opt.active_voices=atoi(s); /* Change to binary string ? */
		    break;
		  case 'c':
		    getarg(&s, &index);
		    next=1;
		    opt.click_removal=atoi(s);
		    break;
		  case 'f':
		    getarg(&s, &index);
		    next=1;
		    printf("Option -f ignored as currently only 4 channel mods"
			   " are supported.\n");
		    break;
		  case 'l':
		    getarg(&s, &index);
		    next=1;
		    opt.loopcount=MAX(atoi(s), 1);
		    break;
		  case 'm':
		    getarg(&s, &index);
		    next=1;
		    opt.maxtime=MAX(atoi(s), 1);
		    break;
		  case 'p':
		    getarg(&s, &index);
		    next=1;
		    opt.start_pos=MAX(atoi(s), 0);
		    break;
		  case 's':
		    getarg(&s, &index);
		    next=1;
		    opt.speed=MAX(atoi(s), 1);
		    break;
		  case 't':
		    getarg(&s, &index);
		    next=1;
		    opt.tempo=MIN(MAX(atoi(s), 32), 255);
		    break;
		  default:
		    printf("Internal error.\n");
		    exit(1);
		}
		s++;
	    }
	    index++;
	}
	else
	    return; /* No more options */
    }
    printf("What are we doing here!?!?\n");
}
