package blanco.plugin.pdf.editors;

import java.io.PrintWriter;
import java.io.StringWriter;

import javax.xml.transform.dom.DOMResult;

import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IFileEditorInput;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import blanco.commons.util.BlancoXmlUtil;
import blanco.pdf.BlancoPdfConstants;
import blanco.pdf.resourcebundle.BlancoPdfResourceBundle;
import blanco.plugin.pdf.BlancoPdfPluginConstants;
import blanco.plugin.pdf.actions.BlancoPdfGenerateAction;

/**
 * エディタ <br>
 * 
 * @author iga
 */
public class BlancoPdfEditor extends AbstractBlancoPdfEditor {
    private static final BlancoPdfResourceBundle fBundle = new BlancoPdfResourceBundle();

    private Composite top = null;

    // ビジュアル領域
    private Label labelBlancoTitle = null;

    private Label labelBlancoSettingId = null;

    private Text textBlancoSettingId = null;

    // TODO 現在使用できていない。
    private Combo comboRuntimePackage = null;

    private Label labelConfdir = null;

    private Text textConfdir = null;

    private Label labelMetadirComment = null;

    private Label labelSettingComment = null;

    private Button buttonExecuteGenerateCheckPdf = null;

    private Button buttonExecuteJavaSource = null;

    public void createPartControl(Composite parent) {
        top = parent;
        top.setSize(new org.eclipse.swt.graphics.Point(1000, 400));

        GridLayout layout = new GridLayout();
        layout.numColumns = 2;
        top.setLayout(layout);

        // スペーサー
        new Label(top, SWT.NONE).setText("");

        labelBlancoTitle = new Label(top, SWT.NONE);
        labelBlancoTitle.setText(BlancoPdfConstants.PRODUCT_NAME
                + " 設定ファイル エディタ (" + BlancoPdfConstants.VERSION + ")");

        // スペーサー
        new Label(top, SWT.NONE).setText("");

        // スペーサー
        new Label(top, SWT.NONE).setText("");

        labelBlancoSettingId = new Label(top, SWT.NONE);
        labelBlancoSettingId.setText("設定ID");
        textBlancoSettingId = new Text(top, SWT.BORDER);
        textBlancoSettingId.setText(BlancoPdfConstants.PRODUCT_NAME);
        textBlancoSettingId.setEditable(false);

        final Label labelRuntimePackage = new Label(top, SWT.NONE);
        labelRuntimePackage.setText("ランタイムパッケージ");
        createComboRuntimePackage();

        labelConfdir = new Label(top, SWT.NONE);
        labelConfdir.setText("構成ディレクトリ");

        textConfdir = new Text(top, SWT.BORDER);
        textConfdir.setText("conf" + BlancoPdfConstants.TARGET_SUBDIRECTORY);

        // スペーサー
        new Label(top, SWT.NONE).setText("");

        labelMetadirComment = new Label(top, SWT.NONE);
        labelMetadirComment.setText("※メタディレクトリは通常変更せずに利用します。");
        labelMetadirComment.setSize(new org.eclipse.swt.graphics.Point(500,
                30 + 20));

        // スペーサー
        new Label(top, SWT.NONE).setText("");

        buttonExecuteGenerateCheckPdf = new Button(top, SWT.NONE);
        buttonExecuteGenerateCheckPdf.setText("ページ確認用 PDF の生成");
        buttonExecuteGenerateCheckPdf
                .addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() {
                    public void widgetSelected(
                            org.eclipse.swt.events.SelectionEvent e) {
                        if (checkInputField() == false) {
                            return;
                        }

                        try {
                            if (checkInputField() == false) {
                                return;
                            }

                            final IFileEditorInput input = (IFileEditorInput) getEditorInput();
                            if (input.getFile().getProject().getFolder(
                                    textConfdir.getText()).exists() == false) {
                                MessageDialog.openWarning(top.getShell(),
                                        "PDF テスト生成", "メタディレクトリ ("
                                                + textConfdir.getText()
                                                + ") が存在しません。処理を中断します。");
                                return;
                            }

                            showBusy(true);
                            // 再入を防止するために必要です。
                            buttonExecuteGenerateCheckPdf.setEnabled(false);

                            String confDir = textConfdir.getText();
                            if (confDir.trim().length() == 0) {
                                confDir = null;
                            }

                            BlancoPdfGenerateAction
                                    .processBlancoGenerateTestPdf(input
                                            .getFile(), top.getShell(),
                                            getProgressMonitor(), confDir);

                            // tmpフォルダを同期
                            BlancoPdfPluginUtil.refreshFolder(input.getFile(),
                                    getProgressMonitor(), "tmp");

                            // フォルダを同期
                            // あくまでも保険として同期を取ります。
                            BlancoPdfPluginUtil
                                    .refreshFolder(input.getFile(),
                                            getProgressMonitor(), textConfdir
                                                    .getText());
                        } catch (Exception ex) {
                            ex.printStackTrace();
                            StringWriter writer = new StringWriter();
                            ex.printStackTrace(new PrintWriter(writer));
                            writer.flush();
                            MessageDialog.openError(top.getShell(), "ソースコード生成",
                                    "回復不能なエラーが発生.:" + ex.toString() + ": "
                                            + writer.toString());
                        } finally {
                            showBusy(false);
                            // 再入を防止するために必要です。
                            buttonExecuteGenerateCheckPdf.setEnabled(true);
                        }
                    }

                });

        // スペーサー
        new Label(top, SWT.NONE).setText("");

        buttonExecuteJavaSource = new Button(top, SWT.NONE);
        buttonExecuteJavaSource.setText("ソースコード生成");
        buttonExecuteJavaSource
                .addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() {
                    public void widgetSelected(
                            org.eclipse.swt.events.SelectionEvent e) {
                        if (checkInputField() == false) {
                            return;
                        }

                        try {
                            if (checkInputField() == false) {
                                return;
                            }

                            final IFileEditorInput input = (IFileEditorInput) getEditorInput();
                            if (input.getFile().getProject().getFolder(
                                    textConfdir.getText()).exists() == false) {
                                MessageDialog.openWarning(top.getShell(),
                                        "ソースコード生成", "メタディレクトリ ("
                                                + textConfdir.getText()
                                                + ") が存在しません。処理を中断します。");
                                return;
                            }

                            showBusy(true);
                            // 再入を防止するために必要です。
                            buttonExecuteJavaSource.setEnabled(false);

                            String runtimePackage = comboRuntimePackage
                                    .getText();
                            if (runtimePackage.trim().length() == 0) {
                                runtimePackage = null;
                            }

                            String confDir = textConfdir.getText();
                            if (confDir.trim().length() == 0) {
                                confDir = null;
                            }

                            BlancoPdfGenerateAction.processBlancoPdfSource(
                                    input.getFile(), top.getShell(),
                                    getProgressMonitor(), runtimePackage,
                                    confDir);

                            // blancoフォルダを同期
                            BlancoPdfPluginUtil.refreshFolder(input.getFile(),
                                    getProgressMonitor(), "blanco");

                            // tmpフォルダを同期
                            BlancoPdfPluginUtil.refreshFolder(input.getFile(),
                                    getProgressMonitor(), "tmp");

                            // フォルダを同期
                            // あくまでも保険として同期を取ります。
                            BlancoPdfPluginUtil
                                    .refreshFolder(input.getFile(),
                                            getProgressMonitor(), textConfdir
                                                    .getText());
                        } catch (Exception ex) {
                            ex.printStackTrace();
                            StringWriter writer = new StringWriter();
                            ex.printStackTrace(new PrintWriter(writer));
                            writer.flush();
                            MessageDialog.openError(top.getShell(), "ソースコード生成",
                                    "回復不能なエラーが発生.:" + ex.toString() + ": "
                                            + writer.toString());
                        } finally {
                            showBusy(false);
                            // 再入を防止するために必要です。
                            buttonExecuteJavaSource.setEnabled(true);
                        }
                    }

                });

        // スペーサー
        new Label(top, SWT.NONE).setText("");

        labelSettingComment = new Label(top, SWT.NONE);
        labelSettingComment.setText("※各々の設定値は "
                + BlancoPdfPluginConstants.TARGET_FILENAME + "ファイルに平文で格納されます。");
        labelSettingComment
                .setSize(new org.eclipse.swt.graphics.Point(500, 20));

        loadFromTextEditor();

        setFocusLostHandler(comboRuntimePackage);
        setFocusLostHandler(textConfdir);
    }

    /**
     * 入力項目のチェックを実施します。 <br>
     * エラーダイアログはこのメソッドで表示します。
     * 
     * @return
     */
    private final boolean checkInputField() {
        boolean isError = false;
        if (textConfdir.getText().length() == 0) {
            textConfdir.setBackground(top.getDisplay().getSystemColor(
                    SWT.COLOR_YELLOW));
            isError = true;
        } else {
            textConfdir.setBackground(top.getDisplay().getSystemColor(
                    SWT.COLOR_INFO_BACKGROUND));
        }

        if (isError) {
            MessageDialog.openWarning(top.getShell(), "必須項目への入力が足りません",
                    "必須項目への入力が足りません。\nハイライト表示されている必須項目に値を入力してください");
        }

        return !isError;
    }

    /**
     * ランタイムパッケージコンボを初期化します。
     * 
     */
    private void createComboRuntimePackage() {
        comboRuntimePackage = new Combo(top, SWT.NONE);
        comboRuntimePackage.add("myapp.jsf");
    }

    protected void loadFromTextEditorInternal(DOMResult argResult) {
        final Node nodeRoot = argResult.getNode();
        if (nodeRoot == null) {
            return;
        }
        final Element elementBlancoPdf = BlancoXmlUtil.getElement(nodeRoot,
                "blanco/target/" + BlancoPdfConstants.PRODUCT_NAME_LOWER);
        if (elementBlancoPdf == null) {
            return;
        }

        final String runtimePackage = elementBlancoPdf
                .getAttribute("runtimepackage");
        if (runtimePackage != null) {
            comboRuntimePackage.setText(runtimePackage);
        }
        final String metadir = elementBlancoPdf.getAttribute("metadir");
        if (metadir != null) {
            textConfdir.setText(metadir);
        }

    }

    /**
     * 保存処理を行います。
     */
    public Document saveToTextEditorInternal() {
        String runtimepackage = null;
        if (comboRuntimePackage.getText().trim().length() > 0) {
            runtimepackage = comboRuntimePackage.getText();
        }

        String metadir = null;
        if (textConfdir.getText().trim().length() > 0) {
            metadir = textConfdir.getText();
        }

        final Document document = BlancoXmlUtil.newDocument();
        final Element eleBlanco = document.createElement("blanco");
        document.appendChild(eleBlanco);

        final Element eleTarget = document.createElement("target");
        eleTarget.setAttribute("name", textBlancoSettingId.getText());
        eleBlanco.appendChild(eleTarget);

        final Element eleBlancoMessage = document
                .createElement(BlancoPdfConstants.PRODUCT_NAME_LOWER);
        eleTarget.appendChild(eleBlancoMessage);

        if (runtimepackage != null) {
            eleBlancoMessage.setAttribute("runtimepackage", runtimepackage);
        }

        if (metadir != null) {
            eleBlancoMessage.setAttribute("metadir", metadir);
        }

        return document;
    }
}