/*
 * blanco Framework
 * Copyright (C) 2004-2005 IGA Tosiki
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 */
package blanco.eclipseplugingen.expand;

import java.io.File;
import java.util.List;

import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import blanco.cg.BlancoCgObjectFactory;
import blanco.cg.transformer.BlancoCgTransformerFactory;
import blanco.cg.valueobject.BlancoCgClass;
import blanco.cg.valueobject.BlancoCgMethod;
import blanco.cg.valueobject.BlancoCgSourceFile;
import blanco.commons.util.BlancoJavaSourceUtil;
import blanco.commons.util.BlancoNameAdjuster;
import blanco.commons.util.BlancoXmlUtil;

public class BlancoEclipsePluginGenExpandPluginUtil {
    /**
     * 内部的に利用するblancoCg用ファクトリ。
     */
    private BlancoCgObjectFactory fCgFactory = null;

    /**
     * 内部的に利用するblancoCg用ソースファイル情報。
     */
    private BlancoCgSourceFile fCgSourceFile = null;

    /**
     * 内部的に利用するblancoCg用クラス情報。
     */
    private BlancoCgClass fCgClass = null;

    public final void expand(final Element elementCommon,
            final NodeList listList, final File directoryTarget) {
        final String pluginName = BlancoXmlUtil.getTextContent(elementCommon,
                "name");
        final String packageName = BlancoXmlUtil.getTextContent(elementCommon,
                "packageName");
        final String description = BlancoXmlUtil.getTextContent(elementCommon,
                "description");

        // 従来と互換性を持たせるため、/mainサブフォルダに出力します。
        final File fileBlancoMain = new File(directoryTarget.getAbsolutePath()
                + "/main");

        fCgFactory = BlancoCgObjectFactory.getInstance();
        fCgSourceFile = fCgFactory.createSourceFile(packageName + ".editors",
                "このソースコードは blanco Frameworkによって自動生成されています。");
        fCgSourceFile.getLangDoc().getDescriptionList().add(
                "Eclipseプラグイン [" + pluginName + "]のユーティリティクラス");

        fCgClass = fCgFactory
                .createClass(BlancoNameAdjuster.toClassName(pluginName)
                        + "PluginUtil", "Eclipseプラグイン [" + pluginName
                        + "]のユーティリティクラス。");
        fCgSourceFile.getClassList().add(fCgClass);

        if (description != null) {
            fCgClass.getLangDoc().getDescriptionList().add(
                    BlancoJavaSourceUtil.escapeStringAsJavaDoc(description)
                            + "<br>");
        }

        fCgSourceFile.getImportList().add("org.eclipse.core.resources.IFile");
        fCgSourceFile.getImportList().add("org.eclipse.core.resources.IFolder");
        fCgSourceFile.getImportList().add(
                "org.eclipse.core.resources.IResource");
        fCgSourceFile.getImportList().add(
                "org.eclipse.core.runtime.CoreException");
        fCgSourceFile.getImportList().add(
                "org.eclipse.core.runtime.IProgressMonitor");

        {
            final BlancoCgMethod method = fCgFactory.createMethod(
                    "refreshFolder", "同一プロジェクト内の 指定フォルダを更新します。");
            fCgClass.getMethodList().add(method);

            method.setStatic(true);

            method.getParameterList().add(
                    fCgFactory.createParameter("input",
                            "org.eclipse.core.resources.IFile",
                            "エディタが現在処理しているファイル"));
            method.getParameterList().add(
                    fCgFactory.createParameter("monitor",
                            "org.eclipse.core.runtime.IProgressMonitor",
                            "Eclipseの進捗モニタ"));
            method.getParameterList().add(
                    fCgFactory.createParameter("folderName",
                            "java.lang.String", "処理対象のフォルダ名"));
            method.setReturn(fCgFactory.createReturn("boolean", ""));
            method.getThrowList().add(
                    fCgFactory.createException(
                            "org.eclipse.core.runtime.CoreException", ""));

            final List listLine = method.getLineList();

            listLine
                    .add("IFolder folderCheck = input.getProject().getFolder(folderName);");
            listLine.add("// キャッシュを確実にクリア。");
            listLine.add("folderCheck.clearHistory(monitor);");
            listLine.add("if (folderCheck.exists()) {");
            listLine
                    .add("folderCheck.refreshLocal(IResource.DEPTH_INFINITE, monitor);");
            listLine.add("return true;");
            listLine.add("}");
            listLine.add("return false;");
        }

        {
            final BlancoCgMethod method = fCgFactory.createMethod(
                    "createFolder", "同一プロジェクト内の 指定フォルダを作成します。");
            fCgClass.getMethodList().add(method);

            method.setStatic(true);

            method.getParameterList().add(
                    fCgFactory.createParameter("input",
                            "org.eclipse.core.resources.IFile",
                            "エディタが現在処理しているファイル"));
            method.getParameterList().add(
                    fCgFactory.createParameter("monitor",
                            "org.eclipse.core.runtime.IProgressMonitor",
                            "Eclipseの進捗モニタ"));
            method.getParameterList().add(
                    fCgFactory.createParameter("argFolderName",
                            "java.lang.String", "処理対象のフォルダ名"));
            method.getThrowList().add(
                    fCgFactory.createException(
                            "org.eclipse.core.runtime.CoreException", ""));

            final List listLine = method.getLineList();

            listLine.add("IFolder folderCurrent = null;");
            listLine.add("String folderName = argFolderName;");
            listLine.add("for (boolean found = false; found == false;) {");
            listLine.add("if (folderName.indexOf('/') < 0) {");
            listLine.add("found = true;");
            listLine.add("if (folderCurrent == null) {");
            listLine
                    .add("folderCurrent = input.getProject().getFolder(folderName);");
            listLine.add("} else {");
            listLine
                    .add("folderCurrent = folderCurrent.getFolder(folderName);");
            listLine.add("}");
            listLine.add("} else {");
            listLine
                    .add("String nextFolder = folderName.substring(0, folderName.indexOf('/'));");
            listLine
                    .add("folderName = folderName.substring(folderName.indexOf('/') + 1);");
            listLine.add("if (folderCurrent == null) {");
            listLine
                    .add("folderCurrent = input.getProject().getFolder(nextFolder);");
            listLine.add("} else {");
            listLine
                    .add("folderCurrent = folderCurrent.getFolder(nextFolder);");
            listLine.add("}");
            listLine.add("}");
            listLine.add("if (folderCurrent.exists() == false) {");
            listLine.add("folderCurrent.create(true, true, monitor);");
            listLine.add("}");
            listLine.add("}");
        }

        {
            final BlancoCgMethod method = fCgFactory.createMethod("findFolder",
                    "同一プロジェクト内の 指定フォルダを検索します。");
            fCgClass.getMethodList().add(method);

            method.setStatic(true);

            method.getParameterList().add(
                    fCgFactory.createParameter("input",
                            "org.eclipse.core.resources.IFile",
                            "エディタが現在処理しているファイル"));
            method.getParameterList().add(
                    fCgFactory.createParameter("monitor",
                            "org.eclipse.core.runtime.IProgressMonitor",
                            "Eclipseの進捗モニタ"));
            method.getParameterList().add(
                    fCgFactory.createParameter("argFolderName",
                            "java.lang.String", "処理対象のフォルダ名"));
            method.setReturn(fCgFactory.createReturn(
                    "org.eclipse.core.resources.IFolder", ""));
            method.getThrowList().add(
                    fCgFactory.createException(
                            "org.eclipse.core.runtime.CoreException", ""));

            final List listLine = method.getLineList();

            listLine.add("IFolder folderCurrent = null;");
            listLine.add("String folderName = argFolderName;");
            listLine.add("for (boolean found = false; found == false;) {");
            listLine.add("if (folderName.indexOf('/') < 0) {");
            listLine.add("found = true;");
            listLine.add("if (folderCurrent == null) {");
            listLine
                    .add("folderCurrent = input.getProject().getFolder(folderName);");
            listLine.add("} else {");
            listLine
                    .add("folderCurrent = folderCurrent.getFolder(folderName);");
            listLine.add("}");
            listLine.add("} else {");
            listLine
                    .add("String nextFolder = folderName.substring(0, folderName.indexOf('/'));");
            listLine
                    .add("folderName = folderName.substring(folderName.indexOf('/') + 1);");
            listLine.add("if (folderCurrent == null) {");
            listLine
                    .add("folderCurrent = input.getProject().getFolder(nextFolder);");
            listLine.add("} else {");
            listLine
                    .add("folderCurrent = folderCurrent.getFolder(nextFolder);");
            listLine.add("}");
            listLine.add("}");
            listLine.add("}");
            listLine.add("return folderCurrent;");
        }

        {
            final BlancoCgMethod method = fCgFactory.createMethod(
                    "deleteFolder", "同一プロジェクト内の 指定フォルダを削除します。");
            fCgClass.getMethodList().add(method);

            method.setStatic(true);

            method.getParameterList().add(
                    fCgFactory.createParameter("input",
                            "org.eclipse.core.resources.IFile",
                            "エディタが現在処理しているファイル"));
            method.getParameterList().add(
                    fCgFactory.createParameter("monitor",
                            "org.eclipse.core.runtime.IProgressMonitor",
                            "Eclipseの進捗モニタ"));
            method.getParameterList().add(
                    fCgFactory.createParameter("folderName",
                            "java.lang.String", "処理対象のフォルダ名"));

            method.getThrowList().add(
                    fCgFactory.createException(
                            "org.eclipse.core.runtime.CoreException", ""));

            final List listLine = method.getLineList();

            listLine
                    .add("IFolder folder = findFolder(input, monitor, folderName);");
            listLine.add("if (folder != null) {");
            listLine.add("folder.delete(true, monitor);");
            listLine.add("}");
        }

        // ソースコードを実際に生成します。
        BlancoCgTransformerFactory.getJavaSourceTransformer().transform(
                fCgSourceFile, fileBlancoMain);
    }
}
