/*
 * 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.BlancoCgLine;
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 BlancoEclipsePluginGenExpandDocumentProvider {
    /**
     * 内部的に利用する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)
                + "DocumentProvider", "Eclipseプラグイン [" + pluginName
                + "]のドキュメントプロバイダクラス。");
        fCgSourceFile.getClassList().add(fCgClass);

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

        fCgClass
                .getExtendClassList()
                .add(
                        fCgFactory
                                .createType("org.eclipse.ui.editors.text.StorageDocumentProvider"));
        fCgSourceFile.getImportList().add("java.io.ByteArrayInputStream");

        fCgSourceFile.getImportList().add("java.io.InputStream");
        fCgSourceFile.getImportList().add(
                "java.io.UnsupportedEncodingException");
        fCgSourceFile.getImportList().add(
                "org.eclipse.core.runtime.CoreException");
        fCgSourceFile.getImportList().add(
                "org.eclipse.core.runtime.IProgressMonitor");
        fCgSourceFile.getImportList().add("org.eclipse.jface.text.IDocument");
        fCgSourceFile.getImportList().add("org.eclipse.ui.IFileEditorInput");
        fCgSourceFile.getImportList().add(
                "org.eclipse.ui.editors.text.StorageDocumentProvider");

        {
            final BlancoCgMethod method = fCgFactory.createMethod(
                    "setDocumentContent", "ドキュメントの読み込み処理をオーバーライドします。");
            fCgClass.getMethodList().add(method);
            method.setAccess("protected");

            method.getParameterList()
                    .add(
                            fCgFactory.createParameter("document",
                                    "org.eclipse.jface.text.IDocument",
                                    "ドキュメントオブジェクト"));
            method.getParameterList().add(
                    fCgFactory.createParameter("contentStream",
                            "java.io.InputStream", "コンテンツのストリーム"));
            method.getParameterList().add(
                    fCgFactory.createParameter("encodingIgnored",
                            "java.lang.String",
                            "エンコーディング指定が呼び出し元から渡されます。しかしこのパラメータは無視されます。"));
            method.getThrowList().add(
                    fCgFactory.createException(
                            "org.eclipse.core.runtime.CoreException", ""));

            final List listLine = method.getLineList();

            final BlancoCgLine line = fCgFactory
                    .createLine("super.setDocumentContent(document, contentStream, \"UTF-8\");");
            line.setDescription("エンコーディングは無視して強制的に UTF-8扱いとします。");
            listLine.add(line);
        }

        {
            final BlancoCgMethod method = fCgFactory.createMethod(
                    "doSaveDocument", "ドキュメントの保存処理をオーバーライドします。");
            fCgClass.getMethodList().add(method);
            method.setAccess("protected");

            method.getParameterList().add(
                    fCgFactory.createParameter("monitor",
                            "org.eclipse.core.runtime.IProgressMonitor",
                            "Eclipseの進捗モニタ"));
            method.getParameterList().add(
                    fCgFactory.createParameter("element", "java.lang.Object",
                            "エレメント"));
            method.getParameterList()
                    .add(
                            fCgFactory.createParameter("document",
                                    "org.eclipse.jface.text.IDocument",
                                    "ドキュメントオブジェクト"));
            method.getParameterList().add(
                    fCgFactory.createParameter("overwrite", "boolean",
                            "上書きかどうか"));

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

            final List listLine = method.getLineList();

            listLine.add("if (element instanceof IFileEditorInput) {");
            listLine.add("// この場所で保存処理を行います。");
            listLine
                    .add("IFileEditorInput input = (IFileEditorInput) element;");
            listLine.add("String editorText = getDocument(input).get();");
            listLine.add("");
            listLine.add("try {");
            listLine
                    .add("input.getFile().setContents(new ByteArrayInputStream(editorText.getBytes(\"UTF-8\")), true, false, monitor);");
            listLine.add("} catch (UnsupportedEncodingException e) {");
            listLine.add("// このケースは存在しません。");
            listLine.add("e.printStackTrace();");
            listLine.add("}");
            listLine.add("}");
        }

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