/*
 * blanco Framework
 * Copyright (C) 2004-2006 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.ant.util.blanco;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import blanco.ant.BlancoAntConstants;
import blanco.ant.util.BlancoAntUtil;
import blanco.commons.util.BlancoFileUtil;
import blanco.commons.util.BlancoNameAdjuster;
import blanco.xml.bind.BlancoXmlMarshaller;
import blanco.xml.bind.valueobject.BlancoXmlDocument;
import blanco.xml.bind.valueobject.BlancoXmlElement;

/**
 * Apache Antのbuild.xmlのうち blanco用のタスクを生成するためのユーティリティクラスです。
 * 
 * @author IGA Tosiki
 */
public class BlancoAntBlancoTemplate {
    public static final String CMDLINE_PREFIX = "ant: ";

    private String fProjectName = null;

    private String fTargetMetaNameLower = null;

    private String fVersion = null;

    private boolean fIsDotNetSupport = true;

    public void setProjectName(final String argProjectName) {
        fProjectName = argProjectName;
    }

    /**
     * 短い名前で小文字。
     * 
     * @param argTargetMetaNameLower
     */
    public void setTargetMetaNameLower(final String argTargetMetaNameLower) {
        fTargetMetaNameLower = argTargetMetaNameLower;
    }

    public void setVersion(final String argVersion) {
        fVersion = argVersion;
    }

    public void setDotNetSupport(final boolean argDotNetSupport) {
        fIsDotNetSupport = argDotNetSupport;
    }

    /**
     * blanco Frameworkのライブラリ用build.xmlを展開します。
     * 
     * @throws IOException
     */
    public void expandLib() throws IOException {
        if (fProjectName == null) {
            throw new IllegalArgumentException("プロジェクト名が未設定です。処理中断します。");
        }
        if (fTargetMetaNameLower == null) {
            throw new IllegalArgumentException("ターゲットメタ小文字が未設定です。処理中断します。");
        }
        if (fVersion == null) {
            throw new IllegalArgumentException("バージョンが未設定です。処理中断します。");
        }

        final BlancoXmlDocument document = new BlancoXmlDocument();

        final BlancoXmlElement element = new BlancoXmlElement();
        document.getChildNodes().add(element);
        element.setLocalName("project");

        BlancoAntUtil.addIndentTab(element);
        BlancoAntUtil.addAttribute(element, "name", fProjectName);
        BlancoAntUtil.addIndentTab(element);
        BlancoAntUtil.addAttribute(element, "default", "build");
        BlancoAntUtil.addIndentTab(element);
        BlancoAntUtil.addAttribute(element, "basedir", ".");

        BlancoAntUtil.addNewLine(element);

        final SimpleDateFormat sdFormat = new SimpleDateFormat("yyyy/MM/dd");
        BlancoAntUtil.addComment(element, BlancoAntConstants.PRODUCT_NAME + "("
                + BlancoAntConstants.VERSION + ")により自動生成されました。 ("
                + sdFormat.format(new Date()) + ")");

        // プロパティ領域。
        BlancoAntUtil.addIndentTab(element);
        BlancoAntUtil.addProperty(element, "version", fVersion);
        BlancoAntUtil.addNewLine(element);
        BlancoAntUtil.addIndentTab(element);
        BlancoAntUtil.addProperty(element, "project", fProjectName);
        BlancoAntUtil.addIndentTab(element);
        BlancoAntUtil.addProperty(element, "project.lower", "blanco"
                + fTargetMetaNameLower);
        BlancoAntUtil.addIndentTab(element);
        BlancoAntUtil.addProperty(element, "project.zip",
                "${project}-${version}-src.zip");
        BlancoAntUtil.addIndentTab(element);
        BlancoAntUtil.addProperty(element, "project.main.jar", fProjectName
                .toLowerCase()
                + "-${version}.jar");
        BlancoAntUtil.addNewLine(element);
        BlancoAntUtil.addIndentTab(element);
        BlancoAntUtil.addProperty(element, "encoding", "Windows-31J");
        BlancoAntUtil.addIndentTab(element);
        BlancoAntUtil.addProperty(element, "eclipse.dir",
                "C:/Program Files/eclipse");

        if (fIsDotNetSupport) {
            BlancoAntUtil.addIndentTab(element);
            BlancoAntUtil.addProperty(element, "dotnet.dir",
                    "C:\\WINDOWS\\Microsoft.NET\\Framework\\v2.0.50727");
        }

        BlancoAntUtil.addNewLine(element);

        BlancoAntUtil.addIndentTab(element);
        BlancoAntUtil.addComment(element, "Antタスク定義 begin");
        BlancoAntUtil.addTaskExternal(element, "blancoanttask",
                "blanco.anttask.task.BlancoAntTaskTask", new String[] { "lib",
                        "lib.ant" });
        BlancoAntUtil.addTaskExternal(element, "blancoconstants",
                "blanco.constants.task.BlancoConstantsTask", new String[] {
                        "lib", "lib.ant" });
        BlancoAntUtil.addTaskExternal(element, "blancomessage",
                "blanco.message.task.BlancoMessageTask", new String[] { "lib",
                        "lib.ant" });
        BlancoAntUtil.addTaskExternal(element, "blancometa2xml",
                "blanco.meta2xml.task.BlancoMeta2XmlTask", new String[] {
                        "lib", "lib.ant" });
        BlancoAntUtil.addTaskExternal(element, "blancoresourcebundle",
                "blanco.resourcebundle.task.BlancoResourceBundleTask",
                new String[] { "lib", "lib.ant" });
        BlancoAntUtil.addTaskExternal(element, "blancovalueobject",
                "blanco.valueobject.task.BlancoValueObjectTask", new String[] {
                        "lib", "lib.ant" });
        BlancoAntUtil.addComment(element, "Antタスク定義 end");

        BlancoAntUtil.addNewLine(element);

        BlancoAntUtil.addComment(element, "自分自身のAntタスク。");
        BlancoAntUtil
                .addTaskExternal(element, fProjectName.toLowerCase(),
                        "blanco." + fTargetMetaNameLower + ".task."
                                + BlancoNameAdjuster.toClassName(fProjectName)
                                + "Task", new String[] { "lib", "lib.ant" });

        BlancoAntBlancoUtil.addTaskPack4Lib(element, fProjectName);
        BlancoAntBlancoUtil.addTaskJar(element, fProjectName,
                fTargetMetaNameLower);
        BlancoAntBlancoUtil.addTaskCompile(element);
        BlancoAntBlancoUtil.addTaskJavadoc(element);
        BlancoAntBlancoUtil.addTaskMeta4Lib(element);
        BlancoAntBlancoUtil.addTaskBuild4Lib(element);

        if (fIsDotNetSupport) {
            BlancoAntBlancoUtil.addTaskDotNetCompile(element);
        }

        new File("./blanco.ant").mkdirs();

        // 実際のソースコード出力処理を行います。
        final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        new BlancoXmlMarshaller().marshal(document, outStream);
        outStream.flush();

        final File fileTarget = new File("./blanco.ant/build."
                + fTargetMetaNameLower + ".lib.xml");
        switch (BlancoFileUtil.bytes2FileIfNecessary(outStream.toByteArray(),
                fileTarget)) {
        case 0:
            break;
        case 1:
            System.out.println(CMDLINE_PREFIX + "create: "
                    + fileTarget.getAbsolutePath());
            break;
        case 2:
            System.out.println(CMDLINE_PREFIX + "update: "
                    + fileTarget.getAbsolutePath());
            break;
        }
    }

    /**
     * blanco Frameworkのプラグイン用build.xmlを展開します。
     * 
     * @throws IOException
     */
    public void expandPlugin() throws IOException {
        if (fProjectName == null) {
            throw new IllegalArgumentException("プロジェクト名が未設定です。処理中断します。");
        }
        if (fTargetMetaNameLower == null) {
            throw new IllegalArgumentException("ターゲットメタ小文字が未設定です。処理中断します。");
        }
        if (fVersion == null) {
            throw new IllegalArgumentException("バージョンが未設定です。処理中断します。");
        }

        final BlancoXmlDocument document = new BlancoXmlDocument();

        final BlancoXmlElement element = new BlancoXmlElement();
        document.getChildNodes().add(element);
        element.setLocalName("project");

        BlancoAntUtil.addIndentTab(element);
        BlancoAntUtil.addAttribute(element, "name", BlancoNameAdjuster
                .toClassName(fProjectName)
                + "Plugin");
        BlancoAntUtil.addIndentTab(element);
        BlancoAntUtil.addAttribute(element, "default", "build");
        BlancoAntUtil.addIndentTab(element);
        BlancoAntUtil.addAttribute(element, "basedir", ".");

        BlancoAntUtil.addNewLine(element);

        final SimpleDateFormat sdFormat = new SimpleDateFormat("yyyy/MM/dd");
        BlancoAntUtil.addComment(element, BlancoAntConstants.PRODUCT_NAME + "("
                + BlancoAntConstants.VERSION + ")により自動生成されました。 ("
                + sdFormat.format(new Date()) + ")");

        // プロパティ領域。
        BlancoAntUtil.addIndentTab(element);
        BlancoAntUtil.addProperty(element, "version", fVersion);
        BlancoAntUtil.addNewLine(element);
        BlancoAntUtil.addIndentTab(element);
        BlancoAntUtil.addProperty(element, "product", "blanco.plugin."
                + fTargetMetaNameLower);
        BlancoAntUtil.addIndentTab(element);
        BlancoAntUtil.addProperty(element, "project.zip",
                "${product}_${version}-src.zip");
        BlancoAntUtil.addIndentTab(element);
        BlancoAntUtil.addProperty(element, "project.plugin32.jar",
                "${product}_${version}-eclipse3.2.jar");
        BlancoAntUtil.addIndentTab(element);
        BlancoAntUtil.addProperty(element, "project.plugin.main.jar",
                fProjectName.toLowerCase() + "plugin.jar");
        BlancoAntUtil.addNewLine(element);
        BlancoAntUtil.addIndentTab(element);
        BlancoAntUtil.addProperty(element, "encoding", "Windows-31J");
        BlancoAntUtil.addIndentTab(element);
        BlancoAntUtil.addProperty(element, "eclipse.dir",
                "C:/Program Files/eclipse");

        BlancoAntUtil.addNewLine(element);

        BlancoAntUtil.addTaskExternal(element, "blancoconstants",
                "blanco.constants.task.BlancoConstantsTask", new String[] {
                        "lib", "lib.ant" });
        BlancoAntUtil.addTaskExternal(element, "blancoeclipseplugingen",
                "blanco.eclipseplugingen.task.BlancoEclipsePluginGenTask",
                new String[] { "lib", "lib.ant" });

        BlancoAntBlancoUtil.addTaskPack4Plugin(element, fProjectName,
                fTargetMetaNameLower);
        BlancoAntBlancoUtil.addTaskBuildPlugin(element, fProjectName,
                fTargetMetaNameLower);
        BlancoAntBlancoUtil.addTaskCompilePlugin(element);
        BlancoAntBlancoUtil.addTaskJavadoc(element);
        BlancoAntBlancoUtil.addTaskMeta4Plugin(element);
        BlancoAntBlancoUtil.addTaskBuild4Plugin(element);

        new File("./blanco.ant").mkdirs();

        // 実際のソースコード出力処理を行います。
        final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        new BlancoXmlMarshaller().marshal(document, outStream);
        outStream.flush();

        final File fileTarget = new File("./blanco.ant/build."
                + fTargetMetaNameLower + ".plugin.xml");
        switch (BlancoFileUtil.bytes2FileIfNecessary(outStream.toByteArray(),
                fileTarget)) {
        case 0:
            break;
        case 1:
            System.out.println(CMDLINE_PREFIX + "create: "
                    + fileTarget.getAbsolutePath());
            break;
        case 2:
            System.out.println(CMDLINE_PREFIX + "update: "
                    + fileTarget.getAbsolutePath());
            break;
        }
    }
}
