package pbl2011.common;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class FileUtil implements CommonConst {
	
	/**
	 * 指定したディレクトリ以下のファイル/ディレクトリをすべて削除する
	 * ※ディレクトリ空でないと削除出来ないため
	 * @param dir 削除対象のディレクトリ
	 */
	public static void deleteDir(File dir) {
		File[] files = dir.listFiles();
		for (File file : files) {
			if (file.isFile()) {
				file.delete();
			} else if (file.isDirectory()) {
				deleteDir(file);
			}
		}
		dir.delete();
	}

	/**
	 * 指定したファイルの全てを読み込む
	 * @param 読み込むファイル
	 */
	public static String readFile(String filePath) {
		StringBuffer buf = new StringBuffer();
		FileReader in = null;
		try {
			in = new FileReader(filePath);
            int ch;
            while ((ch = in.read()) != -1) {
                buf.append((char)ch);
            }
		} catch (IOException e) {
			// ファイルの読み込みに失敗した場合
			e.printStackTrace();
		} finally {
			try {
				in.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return buf.toString();
	}

	/**
	 * 指定したファイルの全てを読み込む
	 * @param in 読み込むファイルのInputStream
	 */
	public static String readFile(InputStream in) {
		StringBuffer buf = new StringBuffer();
		try {
            int ch;
            while ((ch = in.read()) != -1) {
                buf.append((char)ch);
            }
		} catch (IOException e) {
			// ファイルの読み込みに失敗した場合
			e.printStackTrace();
		} finally {
			try {
				in.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return buf.toString();
	}
	
	/**
	 * ユーザが定義したクラス情報をマップとして抽出する
	 * @param lines　ファイル
	 * @return　ユーザが定義したクラス情報マップ　key:クラス名、value:クラスId
	 */
	public static Map<String, Integer> getUserDefClass(List<String> lines) {
		Map<String, Integer> map = new HashMap<String, Integer>();
		for (String line : lines) {
			if (isClass(line)) {
				String[] elements = line.split(DELIMITER);
				if (Util.hasSymbol(elements[2])) {
					List<String> typeNameList = Util.getTypeList(elements[2]);
					map.put(typeNameList.get(0), Integer.valueOf(elements[1]));
				} else {
					map.put(elements[2], Integer.valueOf(elements[1]));
				}
			}
		}
		return map;
	}

	/**
	 * ファイル内で使用されているType情報をすべて抽出する
	 * @param lines　ファイル
	 * @return　ファイル内で使用されているType情報　value:クラス名
	 */
	public static Set<String> getAllTypeSet(List<String> lines) {
		Set<String> set = new HashSet<String>();
		for (String line : lines) {
			if (isClass(line)) {
				String[] elements = line.split(DELIMITER);
				List<String> typeNameList = Util.getTypeList(elements[2]);
				set.addAll(typeNameList);
			}
			if (isAttrib(line)) {
				String[] elements = line.split(DELIMITER);
				set.addAll(Util.getTypeList(elements[2]));
			}
			if (isMethod(line)) {
				String[] elements = line.split(DELIMITER);
				List<String> typeList = Util.getTypeList(elements[2]);
				typeList.remove(NULL);
				set.addAll(typeList);
			}
			if (isParam(line)) {
				String[] elements = line.split(DELIMITER);
				set.addAll(Util.getTypeList(elements[2]));
			}
		}
		return set;
	}
	
	public static int getMaxClassId(Map<String, Integer> UserDefClassList){
		int maxClassId = 0;
		for (Integer classId : UserDefClassList.values()) {
			if (classId > maxClassId) {
				maxClassId = classId;
			}
		}
		return maxClassId;
	}

	public static boolean isClass(String line) {
		return line.startsWith(ClassType.CLASS.alias()) || line.startsWith(ClassType.ABSTRACT_CLASS.alias())
				|| line.startsWith(ClassType.INTERFACE.alias()) || line.startsWith(ClassType.ENUM.alias());
	}

	public static boolean isAttrib(String line) {
		return line.startsWith(MethodAndAttrType.ATTRIB.alias());
	}

	public static boolean isMethod(String line) {
		return line.startsWith(MethodAndAttrType.ABSTRACT_METHOD.alias()) || line.startsWith(MethodAndAttrType.METHOD.alias());
	}

	public static boolean isParam(String line) {
		return line.startsWith(MethodAndAttrType.PARAM.alias());
	}

	public static boolean isArc(String line) {
		return line.startsWith(AssocType.ASSOC.alias()) || line.startsWith(AssocType.INNER.alias())
				|| line.startsWith(AssocType.DEPENDS.alias()) || line.startsWith(AssocType.EXTENDS.alias());
	}

	public static boolean isPackage(String line) {
		return line.startsWith(PackageType.PACKAGE.alias());
	}


}
