import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class FileUtils {

	public static void visitAllFiles(File f, ArrayList<File> files) {
		if (f.isDirectory()) {
			String[] children = f.list();
			for (int i = 0; i < children.length; i++) {
				visitAllFiles(new File(f, children[i]), files);
			}
		} else {
			if (f.toString().endsWith(".ttcn") || f.toString().endsWith(".ttcn_")) {
				files.add(f);
			}
		}
	}

	// -----------------------------------------------------------------------------------------------

	public static void loadConfig(Properties config) throws IOException {
		FileInputStream fis = new FileInputStream(
				"resources/STF475Tools.properties");
		config.load(fis);
		fis.close();
		if (/* (config.get("TempPath") == null) || */
				(config.get("LogPath") == null)
				|| (config.get("ATSPath") == null)) {
			throw new IOException();
		}

	}

	// -----------------------------------------------------------------------------------------------

	public static void loadReferences(Properties references) throws IOException {
		FileInputStream fis = new FileInputStream(
				"resources/references.properties");
		references.load(fis);
		fis.close();
	}

	// -----------------------------------------------------------------------------------------------

	@SuppressWarnings("resource")
  public static void copyFile(File in, File out) throws IOException {
		FileChannel inChannel = new FileInputStream(in).getChannel();
		FileChannel outChannel = new FileOutputStream(out).getChannel();
		try {
			inChannel.transferTo(0, inChannel.size(), outChannel);
		} catch (IOException e) {
			throw e;
		} finally {
			if (inChannel != null)
				inChannel.close();
			if (outChannel != null)
				outChannel.close();
		}
	}

	// -----------------------------------------------------------------------------------------------

	public static int countT3Modules(File f) {
		int moduleCount = 0;
		try {
			FileInputStream fs = new FileInputStream(f.getAbsolutePath());
			DataInputStream in = new DataInputStream(fs);
			BufferedReader br = new BufferedReader(new InputStreamReader(in));

			String strLine = "";
			while ((strLine = br.readLine()) != null) {
				if (strLine.matches("^\\s*module\\s+\\w+\\s*.*")) {
					moduleCount++;
				}
			}
			in.close();
			fs.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return moduleCount;
	}

	// -----------------------------------------------------------------------------------------------

	public static T3ExpectedOutput extractExpectedOutput(File f) {
		T3ExpectedOutput t3ExpectedOutput = new T3ExpectedOutput();

		try {
			FileInputStream fs = new FileInputStream(f.getAbsolutePath());
			DataInputStream in = new DataInputStream(fs);
			BufferedReader br = new BufferedReader(new InputStreamReader(in));

			String strLine = "";
			while ((strLine = br.readLine()) != null) {
				if (strLine.matches("^\\s*\\*+\\s*@verdict\\s*.*")) {
					Matcher matcher = Pattern.compile(
							"^^\\s*\\*+\\s*@verdict\\s*pass\\s*(.*)")
							.matcher(strLine);
					if (matcher.find()) {
						String result = matcher.group(1);
						String[] split = result.split(",");
						t3ExpectedOutput.setExpectedOutput(split[0].trim());
						if (split.length > 1)
							t3ExpectedOutput
									.setExecutionResult(split[1].trim());
					}

					// System.out.println(strLine);
				}
			}
			in.close();
			fs.close();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return t3ExpectedOutput;
	}

	// -----------------------------------------------------------------------------------------------

	public static T3Purpose extractPurpose(File f) {
		T3Purpose t3Purpose = new T3Purpose();

		try {
			FileInputStream fs = new FileInputStream(f.getAbsolutePath());
			DataInputStream in = new DataInputStream(fs);
			BufferedReader br = new BufferedReader(new InputStreamReader(in));

			String strLine = "";
			while ((strLine = br.readLine()) != null) {
				if (strLine.matches("^\\s*\\*+\\s*@purpose\\s*.*")) {
					Matcher matcher = Pattern
							.compile(
									"^\\s*\\*+\\s*@purpose\\s*(\\d+):(.*?)\\s*,\\s*(.*)")
							.matcher(strLine);
					if (matcher.find()) {
						String result = matcher.group(1);
						t3Purpose.setPartReference(Integer.parseInt(result));
						result = matcher.group(2);
						t3Purpose.setClause(result);
						result = matcher.group(3);
						t3Purpose.setPurposeText(result);
//						System.out.println(result);

						// t3ExpectedOutput.setExpectedOutput(split[0].trim());
						// if (split.length > 1)
						// t3ExpectedOutput.setExecutionResult(split[1].trim());
					}

					// System.out.println(strLine);
				}
			}
			in.close();
			fs.close();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return t3Purpose;
	}

	// -----------------------------------------------------------------------------------------------

	public static ArrayList<File> splitT3ModuleFiles(File f) {
		ArrayList<File> files = new ArrayList<File>();
		StringBuffer current = new StringBuffer();
		File newFile = new File(f.getParent() + "//temp.ttcn");
		if (f.exists()) {
			f.renameTo(newFile);
		}

		try {
			FileInputStream fs = new FileInputStream(newFile.getAbsolutePath());
			DataInputStream in = new DataInputStream(fs);
			BufferedReader br = new BufferedReader(new InputStreamReader(in));

			String strLine = "";
			int moduleCounter = 0;
			String currentModuleName = "";

			while ((strLine = br.readLine()) != null) {
				if (strLine.matches("^\\s*module\\s+\\w+\\s*.*")) {
					moduleCounter++;
					if (moduleCounter > 1) { // write file
						String targetFilename = f.getParent() + "//"
								+ currentModuleName + ".ttcn";
						FileWriter fw = new FileWriter(targetFilename);
						fw.write(current.toString());
						fw.close();
						current = new StringBuffer();
						files.add(new File(targetFilename));
					}
					Matcher matcher = Pattern.compile(
							"^\\s*module\\s+(\\w+)\\s*.*").matcher(strLine);
					if (matcher.find()) {
						currentModuleName = matcher.group(1);
					}
				}
				current.append(strLine + "\n");
			}
			// write file
			String targetFilename = f.getParent() + "//" + currentModuleName
					+ ".ttcn";
			FileWriter fw = new FileWriter(targetFilename);
			fw.write(current.toString());
			fw.close();
			in.close();
			fs.close();
			files.add(new File(targetFilename));
			newFile.delete();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return files;
	}

	public static String loadFileToString(File file) throws IOException {
		int len;
		char[] chr = new char[4096];
		final StringBuffer buffer = new StringBuffer();
		BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "ISO-8859-1"));
		try {
			while ((len = reader.read(chr)) > 0) {
				buffer.append(chr, 0, len);
			}
		} finally {
			reader.close();
		}
		return buffer.toString();
	}
	
	public static void saveStringToFile(File file, String str) throws IOException {
		 PrintWriter out = new PrintWriter(new FileWriter(file));
		 out.print(str);
		 out.close();
	}
}
