/******************************************************************************
* Copyright (C) 2013  André Berg and others
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     André Berg <andre.bergmedia@googlemail.com> - initial API and implementation
*     Fabio Zadrozny <fabiofz@gmail.com>           - ongoing maintenance
******************************************************************************/
package org.python.pydev.editor.saveactions;

import java.net.MalformedURLException;
import java.net.URL;

import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.jface.preference.BooleanFieldEditor;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.StringFieldEditor;
import org.eclipse.jface.text.DefaultInformationControl.IInformationPresenter;
import org.eclipse.jface.text.TextPresentation;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
import org.python.pydev.core.SystemUtils;
import org.python.pydev.core.log.Log;
import org.python.pydev.editor.PyEdit;
import org.python.pydev.editor.preferences.PyScopedPreferences;
import org.python.pydev.plugin.PydevPlugin;
import org.python.pydev.shared_ui.field_editors.LabelFieldEditor;
import org.python.pydev.shared_ui.field_editors.LinkFieldEditor;
import org.python.pydev.shared_ui.field_editors.ScopedFieldEditorPreferencePage;
import org.python.pydev.shared_ui.field_editors.ScopedPreferencesFieldEditor;
import org.python.pydev.shared_ui.tooltips.presenter.AbstractTooltipInformationPresenter;
import org.python.pydev.shared_ui.tooltips.presenter.ToolTipPresenterHandler;

/**
 * Preference page for Pydev editor {@code Save Actions}.
 * Save actions are actions performed on file buffers whenever
 * a file resource is saved.
 *
 * @author André Berg
 * @version 0.1
 */
public class PydevSaveActionsPrefPage extends ScopedFieldEditorPreferencePage implements IWorkbenchPreferencePage {

    private class PydevSaveActionsPageLinkListener implements SelectionListener {

        public PydevSaveActionsPageLinkListener() {
        }

        @Override
        public void widgetSelected(SelectionEvent e) {
            try {
                URL url = new URL("http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html");
                SystemUtils.openWebpageInEclipse(url, "SimpleDateFormat Java Docs");
            } catch (MalformedURLException e1) {
                Log.log(e1);
            }
        }

        @Override
        public void widgetDefaultSelected(SelectionEvent e) {
        }

    }

    private StringFieldEditor dateFormatEditor;
    private PydevDateFieldNameEditor fieldNameEditor;
    private BooleanFieldEditor enableDateFieldActionEditor;
    private LinkFieldEditor dateFormatHelpLinkEditor;

    private static final String enableDateFieldActionEditorTooltipFormat = "" +
            "Parses the file being saved for a module level\n" +
            "field with name and value as defined by the custom\n" +
            "name and date format below and updates it to the\n" +
            "current date.";

    private ToolTipPresenterHandler tooltipPresenter;
    private BooleanFieldEditor sortImportsOnSave;

    public PydevSaveActionsPrefPage() {
        super(GRID);
        final IPreferenceStore store = PydevPlugin.getDefault().getPreferenceStore();
        setDescription("Save actions are run whenever a file is saved.\n");
        setPreferenceStore(store);
    }

    public static final String SAVE_ACTIONS_ONLY_ON_WORKSPACE_FILES = "SAVE_ACTIONS_ONLY_ON_WORKSPACE_FILES";
    public static final boolean DEFAULT_SAVE_ACTIONS_ONLY_ON_WORKSPACE_FILES = true;

    public static final String FORMAT_BEFORE_SAVING = "FORMAT_BEFORE_SAVING";
    public static final boolean DEFAULT_FORMAT_BEFORE_SAVING = false;

    public static final String ENABLE_DATE_FIELD_ACTION = "ENABLE_DATE_FIELD_ACTION";
    public static final boolean DEFAULT_ENABLE_DATE_FIELD_ACTION = false;

    public static final String DATE_FIELD_FORMAT = "DATE_FIELD_FORMAT";
    public static final String DEFAULT_DATE_FIELD_FORMAT = "yyyy-MM-dd";

    public static final String DATE_FIELD_NAME = "DATE_FIELD_NAME";
    public static final String DEFAULT_DATE_FIELD_NAME = "__updated__";

    public static final String SORT_IMPORTS_ON_SAVE = "SORT_IMPORTS_ON_SAVE";
    public static final boolean DEFAULT_SORT_IMPORTS_ON_SAVE = false;

    @Override
    protected void createFieldEditors() {

        IInformationPresenter presenter = new AbstractTooltipInformationPresenter() {
            @Override
            protected void onUpdatePresentation(String hoverInfo, TextPresentation presentation) {
            }

            @Override
            protected void onHandleClick(Object data) {
            }
        };

        final Composite p = getFieldEditorParent();

        addField(new BooleanFieldEditor(SAVE_ACTIONS_ONLY_ON_WORKSPACE_FILES,
                "Apply save actions only to files in the workspace?", p));

        addField(new BooleanFieldEditor(FORMAT_BEFORE_SAVING, "Auto-format editor contents before saving?", p));

        addField(new LinkFieldEditor("link_formatpreferences", "Note: config in <a>code formatting preferences</a>", p,
                new SelectionListener() {

                    @Override
                    public void widgetSelected(SelectionEvent e) {
                        String id = "org.python.pydev.plugin.pyCodeFormatterPage";
                        IWorkbenchPreferenceContainer workbenchPreferenceContainer = ((IWorkbenchPreferenceContainer) getContainer());
                        workbenchPreferenceContainer.openPage(id, null);
                    }

                    @Override
                    public void widgetDefaultSelected(SelectionEvent e) {
                    }
                }));

        // Sort imports when file is saved?
        sortImportsOnSave =
                new BooleanFieldEditor(SORT_IMPORTS_ON_SAVE, "Sort imports on save?", p);
        addField(sortImportsOnSave);

        addField(new LinkFieldEditor("link_importpreferences",
                "Note: config in <a>code style: imports preferences</a>", p,
                new SelectionListener() {

                    @Override
                    public void widgetSelected(SelectionEvent e) {
                        String id = "org.python.pydev.ui.importsconf.ImportsPreferencesPage";
                        IWorkbenchPreferenceContainer workbenchPreferenceContainer = ((IWorkbenchPreferenceContainer) getContainer());
                        workbenchPreferenceContainer.openPage(id, null);
                    }

                    @Override
                    public void widgetDefaultSelected(SelectionEvent e) {
                    }
                }));

        tooltipPresenter = new ToolTipPresenterHandler(p.getShell(), presenter,
                "Tip: Click link to open SimpleDateFormat Java docs online.");

        // Enable date field action editor (boolean)
        IPreferenceStore prefStore = getPreferenceStore();
        final String fieldName = prefStore.getString(DATE_FIELD_NAME);
        final String enableDateFieldActionEditorTooltip =
                String.format(enableDateFieldActionEditorTooltipFormat, fieldName);

        enableDateFieldActionEditor =
                new BooleanFieldEditor(ENABLE_DATE_FIELD_ACTION, "Update date field?", p);

        enableDateFieldActionEditor.getDescriptionControl(p).setToolTipText(enableDateFieldActionEditorTooltip);
        addField(enableDateFieldActionEditor);

        // Date field name editor (string)

        fieldNameEditor = new PydevDateFieldNameEditor(DATE_FIELD_NAME, "Date field name:",
                PydevDateFieldNameEditor.UNLIMITED, p);
        fieldNameEditor.getTextControl(p).setToolTipText(String.format("Default is %s", DEFAULT_DATE_FIELD_NAME));
        fieldNameEditor.setEmptyStringAllowed(false);
        //fieldNameEditor.setValidateStrategy(PydevDateFieldNameEditor.VALIDATE_ON_FOCUS_LOST);
        fieldNameEditor.setEnabled(prefStore.getBoolean(ENABLE_DATE_FIELD_ACTION), p);
        addField(fieldNameEditor);

        // Date format editor (string)

        dateFormatEditor = new StringFieldEditor(DATE_FIELD_FORMAT, "Date field format:", StringFieldEditor.UNLIMITED,
                p);
        dateFormatEditor.getTextControl(p).setToolTipText("Uses Java's SimpleDateFormat tokens.");
        dateFormatEditor.setEmptyStringAllowed(false);
        //dateFormatEditor.setValidateStrategy(StringFieldEditor.VALIDATE_ON_FOCUS_LOST);
        dateFormatEditor.setEnabled(prefStore.getBoolean(ENABLE_DATE_FIELD_ACTION), p);
        addField(dateFormatEditor);

        // Token help editor (link)

        final String dateFormatHelpLinkTooltip = "" +
                "All tokens from Java's SimpleDateFormat class\n" +
                "are supported. The most common ones are:\n" +
                "\n" +
                "y\t\tYear\n" +
                "M\t\tMonth in year\n" +
                "d\t\tDay in month\n" +
                "E\t\tDay name in week\n" +
                "H\t\tHour in day (0-23)\n" +
                "h\t\tHour in am/pm (1-12)\n" +
                "m\t\tMinute in hour\n" +
                "s\t\tSecond in minute\n" +
                "\n" +
                "Enclose literal characters in single quotes.";

        dateFormatHelpLinkEditor =
                new LinkFieldEditor("link_dateFormat", "<a>Supported tokens</a>", p,
                        new PydevSaveActionsPrefPage.PydevSaveActionsPageLinkListener(),
                        dateFormatHelpLinkTooltip, tooltipPresenter);
        addField(dateFormatHelpLinkEditor);

        addField(new LabelFieldEditor("__dummy__",
                "I.e.: __updated__=\"2010-01-01\" will be synched on save.", p));

        addField(new ScopedPreferencesFieldEditor(p, PydevPlugin.DEFAULT_PYDEV_SCOPE, this));

    }

    @Override
    public void init(IWorkbench workbench) {
    }

    public static boolean getDateFieldActionEnabled(PyEdit pyEdit) {
        return PyScopedPreferences.getBoolean(ENABLE_DATE_FIELD_ACTION, pyEdit);
    }

    public static boolean getSortImportsOnSave(PyEdit pyEdit) {
        return PyScopedPreferences.getBoolean(SORT_IMPORTS_ON_SAVE, pyEdit);
    }

    public static boolean getFormatBeforeSaving(PyEdit pyEdit) {
        return PyScopedPreferences.getBoolean(FORMAT_BEFORE_SAVING, pyEdit);
    }

    public static String getDateFieldName(PyEdit pyEdit) {
        return PyScopedPreferences.getString(DATE_FIELD_NAME, pyEdit, DEFAULT_DATE_FIELD_NAME);
    }

    public static String getDateFieldFormat(PyEdit pyEdit) {
        return PyScopedPreferences.getString(DATE_FIELD_FORMAT, pyEdit, DEFAULT_DATE_FIELD_FORMAT);
    }

    public static boolean getAutoformatOnlyWorkspaceFiles(IAdaptable projectAdaptable) {
        return PyScopedPreferences.getBoolean(SAVE_ACTIONS_ONLY_ON_WORKSPACE_FILES, projectAdaptable);
    }

    @Override
    protected void performDefaults() {
        super.performDefaults();
        updateDateFieldStringEditorState();
    }

    private void updateDateFieldStringEditorState() {
        final boolean val = enableDateFieldActionEditor.getBooleanValue();
        final Composite p = getFieldEditorParent();
        dateFormatEditor.setEnabled(val, p);
        fieldNameEditor.setEnabled(val, p);
    }

    @Override
    public void propertyChange(PropertyChangeEvent event) {
        super.propertyChange(event);
        if (enableDateFieldActionEditor.equals(event.getSource())) {
            updateDateFieldStringEditorState();
        }
        setValid((dateFormatEditor.isValid() && fieldNameEditor.isValid()));
        updatePageButtons();
    }

    private void updatePageButtons() {
        final boolean valid = isValid();
        final Button defaultButton = getShell().getDefaultButton();
        if (!valid) {
            getApplyButton().setEnabled(false);
            if (defaultButton != null) {
                defaultButton.setEnabled(false);
            }
        } else {
            getApplyButton().setEnabled(true);
            if (defaultButton != null) {
                defaultButton.setEnabled(true);
            }
        }
    }

}
