package smart_gs.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
//import java.io.*;

public class GSPathStringGrammarChecker {
	static GSPathStringIdentifierGrammarChecker idChecker = new GSPathStringIdentifierGrammarChecker ();
	static WindowsHeaderChecker winHeaderChecker = new WindowsHeaderChecker ();

	private static class GSPathStringIdentifierGrammarChecker {
		String zenkakuKanjiKanaOrAscii = "([ˆê-êž]|[‚Ÿ-‚ñ]|[ƒ@-ƒ–]|[\\x20-\\x7e])+";
//		"*/:<>?\|
		String excludedForWin = "[\\x22\\x2a\\x2f\\x3a\\x3c\\x3e\\x3f\\x5c\\x7c]";

		private Pattern patternZenkakuOrAscii;
		private Pattern patternExcludedForWin;

		public GSPathStringIdentifierGrammarChecker() {
			patternZenkakuOrAscii = Pattern.compile(zenkakuKanjiKanaOrAscii);
			patternExcludedForWin = Pattern.compile(excludedForWin);
		}
		
		public boolean checks(String string) {
			if (string.equals(".") || string.equals("..")) return true;
			if (string.charAt(0) == '@' || string.charAt(0) == '#' || string.charAt(0) == '.') return false;
			if (string.length() == 3 &&
					(string.charAt(0) == 'd' || string.charAt(0) == 'D') &&
					(string.charAt(0) == 's' || string.charAt(0) == 'S') &&
					(string.charAt(0) == 'c' || string.charAt(0) == 'C')) {
				return false;
			}
			Matcher matcherZenkakuOrAscii = patternZenkakuOrAscii.matcher(string);
			Matcher matcherExcludedForWin = patternExcludedForWin.matcher(string);
			return matcherZenkakuOrAscii.matches() && ! matcherExcludedForWin.find();
		}
	}
	
	private static class WindowsHeaderChecker {
		String windowsHeader = "([A-Z]|[a-z]):.*";
		private Pattern patternWindowsHeader;

		public WindowsHeaderChecker() {
			patternWindowsHeader = Pattern.compile(windowsHeader);
		}
		
		public boolean checks(String string) {
			Matcher matcherWindowsHeader = patternWindowsHeader.matcher(string);
			return matcherWindowsHeader.matches();
		}
	}
	
	
	public static boolean isGsPath (String string0) {
		String string = GSStandardPath.normalizeSeparators(string0);
		return 
		isGsWinAbsolutePath(string) || 
		isGsUnixAbsolutePath(string) ||
		isGsRelativePath(string);
	}
	
//	\  and / both present
	public static boolean confusingSeparators (String string) {
		return (string.indexOf("\\") != -1) & (string.indexOf("/") != -1);
	}
	
	public static boolean endsWithUnixSeparator (String string) {
		return string.endsWith("/");
	}
	
	public static boolean endsWithWinSeparator (String string) {
		return string.endsWith("\\");
	}
	
	public static boolean endsWithSeparator (String string) {
		return string.endsWith("\\") || string.endsWith("/");
	}
	
	public static boolean hasWinDriveHeader (String string) {
		return winHeaderChecker.checks(string);
	}
	
//	[A-z]:string, where isUnixTypeAbsolutePath(string) == true
	public static boolean isGsWinAbsolutePath (String string) {
		string = GSStandardPath.normalizeSeparators(string);
		if (!hasWinDriveHeader(string)) return false;
		String rest = string.substring(2,string.length());
		if (rest.equals("")) return true;
		return isUnixTypeAbsolutePath(rest);
	}
	
	public static boolean isGsRelativePath (String string) {
		string = GSStandardPath.normalizeSeparators(string);
		return isUnixTypeRelativePath(string);
	}
	
	public static boolean isGsUnixAbsolutePath (String string) {
		string = GSStandardPath.normalizeSeparators(string);
		return isUnixTypeAbsolutePath(string);
	}
	
	// string is assumed to be normalized.
	private static boolean isUnixTypeAbsolutePath (String string) {
		int length = string.length();
		if (length == 0) return false;
		if (string.charAt(0) != '/') return false;
		if (string.length() == 1) return true;
		return isUnixTypeRelativePath (string.substring(1,length));
	}
	
	// string is assumed to be normalized, and the head is not 
	// [A-z]:
	private static boolean isUnixTypeRelativePath (String string) {
		int length = string.length();
		if (length == 0) return false;
		if (string.charAt(0) == '/') return false;
		String names[] = string.split("\\/");
		for (int i =0 ; i < names.length; i++){
			if (!isFileDirIdentifier(names[i])) return false;
		}
		return true;
	}
	
	public static boolean isFileDirIdentifier (String string) {
		string = GSStandardPath.normalizeSeparators(string);
		if (string.equals("")) return false;
		return idChecker.checks(string);
	}
}
