/*Single/solo step conversion in Java, version 3.0
The new steps are appended after the first set of steps (first detected semicolon) because
Java cannot write into the middle of a file; a clone of the original is made and a
temporary file is left behind.
by Rhett Dobson, June 12 2008*/

import java.util.*;
import java.io.*;

public class SMConvert3 {

	public static void main (String args[]) throws IOException {

		final int SIZE = 12; //just needs to be large enough for a single line of steps. max possible is Doubles play which is 8 arrows

		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 = 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
		//I tried to put these in a try-catch block but the compiler generated errors, as if
		//they were no longer in my code...shame, since I would prefer to give the user
		//extra chances to type in a valid file name

		/*File midFile = new File("temp.sm");
		midFile.delete();
		midFile.createNewFile(); */

		File midFile = File.createTempFile("temp","sm");

		File outFile = new File(outp); //destination file
		outFile.delete();
		outFile.createNewFile();

		FileWriter mfw = new FileWriter(midFile);
		BufferedWriter bw = new BufferedWriter(mfw); //need a separate writer

		FileWriter fw = new FileWriter(outp);
		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

		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 = ""; //output string
		String searchMode = ""; //string to search for; this is the opposite of the output string
		if (mode) {
			sMode = solo;
			searchMode = single + ":";
		}
		if (!mode) {
			sMode = single;
			searchMode = solo + ":";
		}
		String header1 = "//---------------";
		String header2 = "----------------";

		//standard delimiter of whitespace is used for all File.next(); calls

		int diffFlag = 0; //both of these flags must equal 1 to proceed with the step transformation
		int modeFlag = 0;
		int lineCounter = 0; //a temporary line counter used to count a small number of lines

		try { //dance-mode + difficulty not found
			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.
				lineCounter++;			 //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(searchMode)) {
					modeFlag = 1;
					lineCounter = 0;
				}
				if (currentLine.equals(difficulty)) {
					System.out.println(lineCounter);
					if (lineCounter == 4) {
						diffFlag = 1; //if the correct difficulty is detected 2 lines later, where it's supposed to be, then both flags can be activated
						lineCounter = 0;
						modeFlag = 1; //turns flag back on because it would have been turned off at lineCounter == 1
						System.out.println("WAT");
					}  else {
						diffFlag = 0;
						modeFlag = 0; //but if the correct difficulty is found later, for another mode, try again.
					}
				}


				if (diffFlag == 1 && modeFlag == 1) break;
			};
		} catch (Exception e) {
			System.out.println("Error: end of file reached, " + difficulty + " for " + searchMode + " not found, terminating.");
			System.exit(1);
		}


		//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); //These decimal numbers are used for the "Groove Radar", a graphics feature in the song selection menu
		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")
				// a comma is too short, 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. this is the left arrow for feet
					trueArray[1] = '0'; //empty hand step in the future solo steps
					trueArray[2] = cArray[1]; //down arrow
					trueArray[3] = cArray[2]; //up arrow
					trueArray[4] = '0'; //right hand
					trueArray[5] = cArray[3]; //right arrow
					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. 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);

	}

}