/*
 * blanco Framework
 * Copyright (C) 2004-2008 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.plugin.svnconf.actions;

import java.lang.reflect.InvocationTargetException;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;

import blanco.plugin.svnconf.BlancoSvnConfPlugin;
import blanco.plugin.svnconf.BlancoSvnConfPluginConstants;
import blanco.plugin.svnconf.editors.BlancoSvnConfEditor;
import blanco.plugin.svnconf.editors.BlancoSvnConfPluginUtil;
import blanco.svnconf.BlancoSvnConfConstants;
import blanco.svnconf.resourcebundle.BlancoSvnConfResourceBundle;
import blanco.svnconf.task.BlancoSvnConfBatchProcess;
import blanco.svnconf.task.valueobject.BlancoSvnConfProcessInput;

public class BlancoSvnConfGenerateAction {
    private static final BlancoSvnConfResourceBundle fBundle = new BlancoSvnConfResourceBundle();

    /**
     * 生成処理を実行します。
     * 
     * @param ifile
     *            処理対象のファイル。
     * @param shell
     *            親のシェル。
     * @param metaDir
     *            メタディレクトリ。
     * @param argAcceptLowerCaseUserName
     *            小文字化されたユーザ名を受け付けるかどうか。
     * @throws InvocationTargetException
     *             実行時の例外。
     * @throws InterruptedException
     *             割り込み例外。
     */
    public static final void process(final IFile ifile, final Shell shell,
            final String metaDir, final boolean argAcceptLowerCaseUserName)
            throws InvocationTargetException, InterruptedException {
        if (ifile.getProject().getFolder(metaDir).exists() == false) {
            MessageDialog.openWarning(shell, "ソースコード生成", "メタディレクトリ (" + metaDir
                    + ") が存在しません。処理を中断します。");
            return;
        }

        // プロジェクトのルートフォルダを取得。
        final String rootFolder = ifile.getProject().getLocation().toFile()
                .getAbsolutePath();
        // MessageDialog.openInformation(shell, "ルート", rootFolder);

        try {
            PlatformUI.getWorkbench().getProgressService().busyCursorWhile(
                    new IRunnableWithProgress() {
                        public void run(final IProgressMonitor monitor)
                                throws InvocationTargetException,
                                InterruptedException {
                            try {
                                monitor.beginTask(
                                        BlancoSvnConfConstants.PRODUCT_NAME
                                                + "設定ファイル生成", 10);

                                BlancoSvnConfEditor.refreshAllFolder(ifile,
                                        shell, metaDir, monitor);
                                if (monitor.isCanceled()) {
                                    return;
                                }

                                // テンポラリフォルダを一旦削除します。
                                BlancoSvnConfPluginUtil
                                        .deleteFolder(
                                                ifile,
                                                monitor,
                                                "tmp"
                                                        + BlancoSvnConfConstants.TARGET_SUBDIRECTORY);
                                if (monitor.isCanceled()) {
                                    return;
                                }

                                // ディレクトリ作成は この箇所で事前に実施します。
                                BlancoSvnConfPluginUtil.createFolder(ifile,
                                        monitor, "meta");
                                BlancoSvnConfPluginUtil.createFolder(ifile,
                                        monitor, "blanco.svnconf");
                                BlancoSvnConfPluginUtil
                                        .createFolder(
                                                ifile,
                                                monitor,
                                                "tmp"
                                                        + BlancoSvnConfConstants.TARGET_SUBDIRECTORY);

                                monitor.subTask(fBundle
                                        .getMetafileDisplayname()
                                        + " (*.xls)を処理します");
                                monitor.worked(1);

                                final BlancoSvnConfProcessInput input = new BlancoSvnConfProcessInput();
                                input.setMetadir(rootFolder + "/" + metaDir);
                                input.setTargetdir(rootFolder + "/"
                                        + "blanco.svnconf");
                                input.setTmpdir(rootFolder + "/tmp");
                                input
                                        .setAcceptLowerCaseUserName(argAcceptLowerCaseUserName);
                                new BlancoSvnConfBatchProcess().process(input);
                                // TODO コールバックによる進捗表示の実現。

                                BlancoSvnConfEditor.refreshAllFolder(ifile,
                                        shell, metaDir, monitor);
                                if (monitor.isCanceled()) {
                                    return;
                                }

                                if (BlancoSvnConfPluginConstants.IS_DEBUG) {
                                    Thread.sleep(1000);
                                }
                            } catch (Exception e) {
                                // 最終防衛ライン
                                e.printStackTrace();
                                throw new InvocationTargetException(e, e
                                        .toString());
                            } catch (Error e) {
                                // 最終防衛ライン
                                e.printStackTrace();
                                throw new InvocationTargetException(e, e
                                        .toString());
                            } finally {
                                // 最後の最後では done扱いとします。
                                monitor.done();
                            }
                        }
                    });
        } catch (InvocationTargetException ex) {
            BlancoSvnConfPlugin.log(ex);
            // 例外の中から本当の原因を取り出すことがポイントです。
            MessageDialog.openWarning(shell, "ソースコード生成",
                    "例外が発生しました。処理を中断します。\n" + ex.getCause().toString());
            ex.printStackTrace();
        } catch (InterruptedException ex) {
            BlancoSvnConfPlugin.log(ex);
            MessageDialog.openWarning(shell, "ソースコード生成",
                    "割り込み中断例外が発生しました。処理を中断します。\n" + ex.toString());
            ex.printStackTrace();
        } catch (Exception ex) {
            BlancoSvnConfPlugin.log(ex);
            MessageDialog.openWarning(shell, "ソースコード生成",
                    "予期せぬ例外が発生しました。処理を中断します。\n" + ex.toString());
            ex.printStackTrace();
        } catch (Error er) {
            BlancoSvnConfPlugin.log(er);
            MessageDialog.openWarning(shell, "ソースコード生成",
                    "予期せぬエラーが発生しました。処理を中断します。\n" + er.toString());
            er.printStackTrace();
        }
    }
}