package pbl2011.common;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import pbl2011.model.ClassModel;
import pbl2011.model.ClassNode;
import pbl2011.model.PackageManager;

public class BuiltInClass implements CommonConst {
	private static BuiltInClass instance = new BuiltInClass();
	private static final String PATH_BUILT_IN_CLASS_CONF = "conf/builtInClass.conf";

	public static BuiltInClass getInstance(){
		return instance;
	}
	
	public enum PrimitiveType {
		VOID("void"),
		BOOLEAN("boolean"),
		BYTE("byte"),
		CHAR("char"),
		DOUBLE("double"),
		FLOAT("float"),
		INT("int"),
		LONG("long"),
		SHORT("short"),
		CONSTRACTOR("");

		private String code;

		private PrimitiveType(String code) {
			this.code = code;
		}

		public String code() {
			return this.code;
		}

	}

	public static List<ClassNode> getBuiltinClassNodeList() {
		return instance.getClassNodeList();
	}

	/**
	 * クラス図エディターが起動時にロードするクラスをリストで返却する プリミティブ型はJavaの言語仕様的に必須のため常にロードする
	 * その他クラスは必要に応じてファイルに記載しているものーロードする
	 * 
	 * @return　クラス図エディターが起動時にロードするクラスをリスト
	 */
	private List<ClassNode> getClassNodeList() {

		List<ClassNode> builtInClassList = new ArrayList<ClassNode>();
		int id = SYSTESM_USE_MIN_ID;

		// primitive型の登録
		for (PrimitiveType primitive : PrimitiveType.values()) {
			ClassNode classNode = createClassNode(id++, PACKAGE_DEFAULT_ID,
					primitive.code);
			builtInClassList.add(classNode);

		}
		
		// 設定ファイルからのクラスの読込み
		BufferedReader br = null;
		InputStream in = null;
		String line;
		try {
		    ClassLoader cloader = Util.getClassLoader(BuiltInClass.class);
		    in = cloader.getResourceAsStream(PATH_BUILT_IN_CLASS_CONF);
		    InputStreamReader isr = new InputStreamReader(in);
		    
			br = new BufferedReader(isr);

			while ((line = br.readLine()) != null) {
				if (line.startsWith("#")) { // #で始まる行はコメント行
					continue;
				}
				String[] elements = line.split(DELIMITER);
				PackageManager.add(elements[0]);
				if (elements[2].equals(Boolean.TRUE.toString())) {
					ClassNode classNode = createClassNode(id++,
							PackageManager.getPackageId(elements[0]),
							elements[1]);
					builtInClassList.add(classNode);
				} else {
					id++;
				}
			}
		} catch (IOException e) {
			// ファイルの読み込みに失敗した場合
			e.printStackTrace();
		} finally {
			try {
				in.close();
				br.close();
			} catch (IOException e) {
				// ファイルのクローズに失敗した場合
				e.printStackTrace();
			}
		}
		return builtInClassList;
	}
	
	protected ClassNode createClassNode(int classId, int packageId, String className){
		return new ClassModel(classId, packageId, className);
	}

}
