/*Single/solo step conversion in Java, version 2.0
If the input file and output file have the same names, the new steps are appended after
the first set of steps (first detected semicolon). A temporary file is left behind.
Error checking will also be added later.
by Rhett Dobson, June 12 2008*/

import java.util.*;
import java.io.*;

public class SMConvert2 {

	public static void main (String args[]) throws IOException {

		final int SIZE = 10; //just needs to be large enough for a single line of steps

		Scanner s = new Scanner(System.in); //user input

		System.out.println("Single/solo step converter, by Rhett Dobson");
		System.out.println("");

		System.out.print("Enter file name (.sm files only): ");
		String inf = s.nextLine();
		char[] trick = new char[inf.length() + 1];
		inf.getChars(0, inf.length() - 3,trick,0); //copies just the file name without .sm
		trick[inf.length() - 3] = '2'; //correcting for the + 1
		trick[inf.length() - 2] = '.';
		trick[inf.length() - 1] = 's'; //so "steps.sm" for input becomes "steps2.sm" for output
		trick[inf.length()] = 'm';
		String outp = "";
		outp = String.copyValueOf(trick); //makes a near-clone of the original file

		File inFile = new File(inf); //input file
		Scanner f = new Scanner(inFile); //file scanner

		File midFile = new File("temp.sm"); //temporary intermediate file
		midFile.delete();
		midFile.createNewFile(); //I'm aware of createTempFile but that's for evil software corporations

		File outFile = new File(outp); //temporary intermediate file
		outFile.delete();
		outFile.createNewFile();

		FileWriter mfw = new FileWriter(midFile);
		BufferedWriter bw = new BufferedWriter(mfw); //need a separate writer

		FileWriter fw = new FileWriter(outp); //output file, which happens to be the same as the input file
		BufferedWriter outw = new BufferedWriter(fw);

		System.out.println("Specify conversion mode: ");
		System.out.println("1) Single to Solo");
		System.out.println("2) Solo to Single");
		int m = s.nextInt();
		boolean mode = true; //single->solo
		if (m == 2 ) mode = false; //solo->single
		/*POTENTIAL BUG:
		user could get an array out of bounds exception if they try to convert steps that actually
		already single to single*/

		System.out.println("");

		System.out.println("Specify difficulty: ");
		System.out.println("1) Beginner");
		System.out.println("2) Easy");
		System.out.println("3) Medium");
		System.out.println("4) Hard");
		System.out.println("5) Challenge");
		System.out.println("6) Edit");
		m = s.nextInt();

		String difficulty = "Challenge:"; //If there's going to be only one difficulty, usually people pick this one

		switch (m) {

			case 1:
				difficulty = "Beginner:";
				break;

			case 2:
				difficulty = "Easy:";
				break;

			case 3:
				difficulty = "Medium:";
				break;

			case 4:
				difficulty = "Hard:";
				break;

			case 5:
				difficulty = "Challenge:";
				break;

			case 6:
				difficulty = "Edit:";
				break;

		}

		String currentLine;
		char[] cArray = new char[SIZE];
		char[] trueArray = new char[6]; //large character array for single->solo
		char[] falseArray = new char[4]; //small array for solo->single
		String single = "dance-single";
		String solo = "dance-solo";
		String sMode = "";
		if (mode) sMode = solo;
		if (!mode) sMode = single;
		String header1 = "//---------------";
		String header2 = "----------------";

		//standard delimiter of whitespace is used for all File.next(); calls
		while (true) {
			currentLine = f.next();
			outw.write(currentLine); //write starting stuff to new file, but not to temp file
			outw.newLine();			 //this method of copying destroys the pretty spaces but that's fine.
									 //Stepmania can still read it and will in fact fix it if the steps
									 //are re-saved in its native Edit mode
			if (currentLine.equals(difficulty)) break; //search until matching difficulty is found
		};

		//fabricate header. literal string is Description
		bw.write(header1 + sMode + " - Copied with SMConvert" + header2);
		bw.newLine();
		bw.write("#NOTES:");
		bw.newLine();
		bw.write("     " + sMode + ":");
		bw.newLine();
		bw.write("     Copied with SMConvert:"); //Description again
		bw.newLine();
		bw.write("     " + difficulty);
		bw.newLine();
		currentLine = f.next(); //now resume with file buffer
		bw.write("     " + currentLine); //numerical foot rating. 5 space indent needs to be re-added due to next()'s delimiter
		bw.newLine();

		currentLine = f.next();
		bw.write("     " + currentLine); //mysterious decimal numbers...may be durations of held notes
		bw.newLine();
		//now the rest is done algorithmically

	    currentLine = f.nextLine();
	    currentLine = currentLine.trim(); //needed for next if statement
	    if (currentLine.equals("// measure 1")) currentLine = f.nextLine();
	    //if measure numbers are intact (Stepmania 4.0 feature?) skip the first one. otherwise they are
	    //attached to the commas between measures which will be skipped anyway

		do {

			if (currentLine.length() > 3 && currentLine.length() < 7) { //if this line contains step data
				// (i.e. looks like "0100" or "10001M")
				// either a comma or a "// measure #" will be too long.
				// 'M' means there's a mine there so regexps would be tricky...
				/* would this work?
				 Pattern p = Pattern.compile("[\dM]");
				 Matcher m = p.matcher("[M0-4]");
 				 boolean b = m.matches();*/

				cArray = currentLine.toCharArray();

				if (mode) { //single->solo
					trueArray[0] = cArray[0]; //manually grab individual characters
					trueArray[1] = '0'; //empty hand step in the future solo steps
					trueArray[2] = cArray[1];
					trueArray[3] = cArray[2];
					trueArray[4] = '0'; //right hand
					trueArray[5] = cArray[3];
					bw.write(String.copyValueOf(trueArray)); //write a string made from the new array
					bw.newLine();
				}

				if (!mode) { //solo->single
					falseArray[0] = cArray[0];
					falseArray[1] = cArray[2]; //avoid the hand sensor columns
					falseArray[2] = cArray[3];
					falseArray[3] = cArray[5];

					bw.write(String.copyValueOf(falseArray));
					bw.newLine();
				}

			} //else {
			if (currentLine.equals(",") || currentLine.length() > 6) {
				bw.write(","); //measure numbers can be added later, but they're not so helpful if
							   //you're just viewing steps in Notepad
				bw.newLine();
			}

			currentLine = f.nextLine(); //proceed to next line
			outw.write(currentLine); //regardless, the line of old stuff steps needs to be copied
			outw.newLine();

		} while (currentLine.equals(";") == false); //stepfiles end with a semicolon

		bw.write(";"); //end of temp file's stepfile
		bw.close(); //writer must be closed to save the file
		//temp.sm has everything we need in it, now we copy it line by line into the original file
		//at this point, outw should have copied all of the existing stuff into the new file, now we
		//insert the contents of the temp file

		Scanner e = new Scanner(midFile);

		do {

			currentLine = e.nextLine(); //e is the temp file's Scanner
			outw.write(currentLine);
			outw.newLine();

		} while (currentLine.equals(";") == false); //we know for sure this is the last character

		while (currentLine.equals(";") == false) { //might be end of file

			currentLine = f.nextLine(); //now do whatever is left of the original file and copy that
			outw.write(currentLine);
			outw.newLine();

		};

		outw.close();
		midFile.delete(); //for some reason the temporary file doesn't get deleted

		System.out.println("Done. Check " + outp);

	}

}
