package com.kurukurupapa.tryandroid.fw.apt;

import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Properties;

import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.tools.JavaFileObject;
import javax.tools.Diagnostic.Kind;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;


public class DaoGenerater {
	public void generateSource(Element element,
			ProcessingEnvironment processingEnv) {
		PrintWriter writer = null;

		try {
			TableData data = getData(element, processingEnv);
			JavaFileObject file = AptUtils.createSourceFile(
					data.getDestClassName(), processingEnv);
			writer = new PrintWriter(file.openWriter(), true);
			writeClass(writer, data);
			writer.flush();

		} catch (Exception e) {
			Messager messager = processingEnv.getMessager();
			messager.printMessage(Kind.ERROR, e.toString());
			throw new RuntimeException(e);

		} finally {
			if (writer != null) {
				writer.close();
			}
		}
	}

	private TableData getData(Element classElement,
			ProcessingEnvironment processingEnv) {
		TableData data = new TableData();

		String packageName = AptUtils.getPackageName(classElement,
				processingEnv);
		data.setSrcPackageName(packageName);
		data.setSrcSimpleName(classElement.getSimpleName().toString());
		data.setDestPackageName(packageName);
		data.setDestSimpleName(data.getSrcSimpleName() + "Dao");

		for (Element element : classElement.getEnclosedElements()) {
			// フィールドのみ対象
			if (element.getKind() != ElementKind.FIELD) {
				continue;
			}
			// Excludeアノテーションの付いているフィールドは無視
			if (element.getAnnotation(TaaExclude.class) != null) {
				continue;
			}
			String type = element.asType().toString();
			String name = element.getSimpleName().toString();
			data.addField(type, name, element);
		}

		return data;
	}

	private void writeClass(PrintWriter w, TableData data) throws Exception {
		// Velocity初期化
		// 当APTをJARに入れても動作するようにStreamとして設定ファイルを読み込む。
		InputStream is = getClass().getClassLoader().getResourceAsStream(
				"velocity.properties");
		if (is == null) {
			throw new RuntimeException("Velocity設定ファイルが見つかりませんでした。URL="
					+ getClass().getClassLoader().getResource(
							"velocity.properties"));
		}
		Properties props = new Properties();
		props.load(is);
		Velocity.init(props);

		// データ詰め込み
		VelocityContext context = new VelocityContext();
		context.put("data", data);

		// データとテンプレートをマージ
		Template template = Velocity.getTemplate("Dao.vm", "UTF-8");
		template.merge(context, w);
	}
}
