package com.meapsoft.composers;

import gnu.getopt.Getopt;

import java.io.IOException;
import java.util.Iterator;
import java.util.Vector;

import com.meapsoft.EDLChunk;
import com.meapsoft.EDLFile;
import com.meapsoft.FeatChunk;
import com.meapsoft.FeatFile;
import com.meapsoft.ParserException;

/**
 *
 * @author Douglas Repetto
 */

public class RotComposer extends Composer
{
	public static String description = "RotComposer rotates the beats in each measure" +		" by a selectable number of positions. You can set the number of beats/measure, the number " +		"of positions to rotate, and the direction of rotation.";
	
	String outFileName = "rot.edl";

	FeatFile featFile;
	boolean debug = false;
	
	int beatsPerMeasure = 4;
	int numPositions = 1;
	boolean rotateRight = true;
	
	public RotComposer(String featFN, String outFN, int beatsPerMeasure, int numPositions, boolean left)
	{
		this(new FeatFile(featFN), new EDLFile(outFN), beatsPerMeasure, numPositions, left);
	}

	public RotComposer(FeatFile featFN, EDLFile outFN, int beatsPerMeasure, int numPositions, boolean left)
	{
		if (featFN == null || outFN == null)
			return;
			
		featFile = featFN;
		outFile = outFN;

		if(outFile == null)
			outFile = new EDLFile("");
			
		this.beatsPerMeasure = beatsPerMeasure;
		this.numPositions = numPositions;
		rotateRight = !left;
	}

	public void printUsageAndExit() 
	{
		System.out.println("Usage: RotComposer [-options] features.feat \n\n" + 
			   "  where options include:\n" + 
			   "	-b beats_per_measure	the number of beats in a measure (defaults to four)\n" +
			   "	-n num_positions	the number of positions to rotate (defaults to one)\n" +
			   "	-l 				rotate left (default is rotate right)" +
			   "    -o output_file  the file to write the output to (defaults to shuffle.edl)\n" +
			   "    -g              debug mode (prints out chunk features on each line of output file)");
		System.out.println();
		System.exit(0);
	}

	public RotComposer(String[] args) 
	{
		if(args.length == 0)
			printUsageAndExit();

		Vector features = new Vector();

		// Parse arguments
		String argString = "b:n:l:o:g";

		Getopt opt = new Getopt("RotComposer", args, argString);
		opt.setOpterr(false);
        
		int c = -1;
		while ((c =opt.getopt()) != -1) 
		{
			switch(c) 
			{
			case 'b':
				beatsPerMeasure = new Integer(opt.getOptarg()).intValue();
				break;
			case 'n':
				numPositions = new Integer(opt.getOptarg()).intValue();
				break;
			case 'l':
				rotateRight = false;
				break;
			case 'o':
				outFileName = opt.getOptarg();
				break;
			case 'g':
				debug = true;
				break;
			case '?':
				printUsageAndExit();
				break;
			default:
				System.out.print("getopt() returned " + c + "\n");
			}
		}
        
		// parse arguments
		int ind = opt.getOptind();
		if(ind > args.length)
			printUsageAndExit();
        
		featFile = new FeatFile(args[args.length-1]);
		outFile = new EDLFile(outFileName);

		System.out.println("Composing " + outFileName + 
						   " from " +  args[args.length-1] + ".");
	}

	public void setup() throws IOException, ParserException
	{
		super.setup();

		if(!featFile.haveReadFile)
			featFile.readFile();

		if(featFile.chunks.size() == 0)
			throw new ParserException(featFile.filename, "No chunks found");

        progress.setMaximum(featFile.chunks.size());
	}
    

	public EDLFile compose()
	{
		Iterator c = featFile.chunks.iterator();
		int totalChunks = featFile.chunks.size();
		
		double currTime = 0;
		int currStartBeat = 0;
		int localStartBeat = 0;
		int currPosition = 0;
				
		if (rotateRight)
			localStartBeat = beatsPerMeasure - numPositions;
		else
			localStartBeat = numPositions;
		
		//System.out.println("localStartBeat: " + localStartBeat);
		
		for (int measure = 0; measure < totalChunks/beatsPerMeasure; measure++)
		{
			FeatChunk chunks[] = new FeatChunk[beatsPerMeasure];
			int numBeatsFound = 0;
			
			for (int i = 0; i < beatsPerMeasure; i++)
				chunks[i] = (FeatChunk)c.next();

			currPosition = localStartBeat;
			
			for (int i = 0; i < beatsPerMeasure; i++)
			{
				//System.out.println("i: " + i + " currPosition: " + currPosition);
				
				EDLChunk newChunk = new EDLChunk(chunks[currPosition], currTime);
				outFile.chunks.add(newChunk);
				currTime += newChunk.length;
				
				currPosition++;
				currPosition %= beatsPerMeasure;
			}
			
            progress.setValue(progress.getValue()+1);	
		}

		// outFile now contains some chunks.
		outFile.haveReadFile = true;

		return outFile;
	} 

	public static void main(String[] args) 
	{
		RotComposer m = new RotComposer(args);
		long startTime = System.currentTimeMillis();
		m.run();
		System.out.println("Done. Took " +
						   ((System.currentTimeMillis() - startTime)/1000.0)
						   + "s");
		System.exit(0);
	}
}
