/*******************************************************************************
 * Copyright (c) 2000, 2005 IBM Corporation 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.ui.internal.ide.dialogs;

import java.text.MessageFormat;

import org.eclipse.core.resources.IWorkspaceDescription;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Preferences;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
import org.eclipse.ui.internal.ide.IIDEHelpContextIds;

/**
 * The FileStatesPage is the page used to set the file states sizes for the workbench.
 */
public class FileStatesPage extends PreferencePage implements
        IWorkbenchPreferencePage, Listener {

	private static final int FAILED_VALUE = -1;

    //Set the length of the day as we have to convert back and forth
    private static final long DAY_LENGTH = 86400000;

    private static final long MEGABYTES = 1024 * 1024;

    private Text longevityText;

    private Text maxStatesText;

    private Text maxStateSizeText;

    //Choose a maximum to prevent OutOfMemoryErrors
    private int FILE_STATES_MAXIMUM = 10000;

    private long STATE_SIZE_MAXIMUM = 100;

    /**
     * This method takes the string for the title of a text field and the value for the
     * text of the field.
     * @return org.eclipse.swt.widgets.Text
     * @param labelString java.lang.String
     * @param textValue java.lang.String
     * @param parent Composite 
     */
    private Text addLabelAndText(String labelString, String textValue,
            Composite parent) {
        Label label = new Label(parent, SWT.LEFT);
        label.setText(labelString);

        Text text = new Text(parent, SWT.LEFT | SWT.BORDER);
        GridData data = new GridData();
        text.addListener(SWT.Modify, this);
        data.horizontalAlignment = GridData.FILL;
        data.grabExcessHorizontalSpace = true;
        data.verticalAlignment = GridData.CENTER;
        data.grabExcessVerticalSpace = false;
        text.setLayoutData(data);
        text.setText(textValue);
        return text;
    }

    /**
     * Recomputes the page's error state by validating all
     * the fields.
     */
    private void checkState() {
        // Assume invalid if the controls not created yet
        if (longevityText == null || maxStatesText == null
                || maxStateSizeText == null) {
            setValid(false);
            return;
        }

        if (validateLongTextEntry(longevityText) == FAILED_VALUE) {
            setValid(false);
            return;
        }

        if (validateMaxFileStates() == FAILED_VALUE) {
            setValid(false);
            return;
        }

        if (validateMaxFileStateSize() == FAILED_VALUE) {
            setValid(false);
            return;
        }

        setValid(true);
        setErrorMessage(null);
    }

    /* 
     * Create the contents control for the workspace file states.
     * @returns Control
     * @param parent Composite
     */
    protected Control createContents(Composite parent) {

    	PlatformUI.getWorkbench().getHelpSystem().setHelp(parent,
                IIDEHelpContextIds.FILE_STATES_PREFERENCE_PAGE);

        // button group
        Composite composite = new Composite(parent, SWT.NONE);
        GridLayout layout = new GridLayout();
        layout.numColumns = 2;
        composite.setLayout(layout);

        IWorkspaceDescription description = getWorkspaceDescription();

        //Get the current value and make sure we get at least one day out of it.
        long days = description.getFileStateLongevity() / DAY_LENGTH;
        if (days < 1)
            days = 1;

        long megabytes = description.getMaxFileStateSize() / MEGABYTES;
        if (megabytes < 1)
            megabytes = 1;

        this.longevityText = addLabelAndText(IDEWorkbenchMessages.FileHistory_longevity, String
                .valueOf(days), composite);
        this.maxStatesText = addLabelAndText(IDEWorkbenchMessages.FileHistory_entries, String
                .valueOf(description.getMaxFileStates()), composite);
        this.maxStateSizeText = addLabelAndText(IDEWorkbenchMessages.FileHistory_diskSpace,
                String.valueOf(megabytes), composite);

        checkState();

        //Create a spacing label to breakup the note from the fields
        Label spacer = new Label(composite, SWT.NONE);
        GridData spacerData = new GridData();
        spacerData.horizontalSpan = 2;
        spacer.setLayoutData(spacerData);

        Composite noteComposite = createNoteComposite(parent.getFont(),
                composite, IDEWorkbenchMessages.Preference_note, IDEWorkbenchMessages.FileHistory_restartNote);
        GridData noteData = new GridData();
        noteData.horizontalSpan = 2;
        noteComposite.setLayoutData(noteData);

        applyDialogFont(composite);

        return composite;
    }

    /**
     * Get the Workspace Description this page is operating on.
     * @return org.eclipse.core.resources.IWorkspaceDescription
     */
    private IWorkspaceDescription getWorkspaceDescription() {
        return ResourcesPlugin.getWorkspace().getDescription();
    }

    /**
     * Sent when an event that the receiver has registered for occurs.
     *
     * @param event the event which occurred
     */
    public void handleEvent(Event event) {
        checkState();
    }

    /**
     * Initializes this preference page for the given workbench.
     * <p>
     * This method is called automatically as the preference page is being created
     * and initialized. Clients must not call this method.
     * </p>
     *
     * @param workbench the workbench
     */
    public void init(org.eclipse.ui.IWorkbench workbench) {
    }

    /**
     * Performs special processing when this page's Defaults button has been pressed.
     * Reset the entries to thier default values.
     */
    protected void performDefaults() {
        super.performDefaults();

        Preferences prefs = ResourcesPlugin.getPlugin().getPluginPreferences();

        long days = prefs
                .getDefaultLong(ResourcesPlugin.PREF_FILE_STATE_LONGEVITY)
                / DAY_LENGTH;
        long megabytes = prefs
                .getDefaultLong(ResourcesPlugin.PREF_MAX_FILE_STATE_SIZE)
                / MEGABYTES;
        this.longevityText.setText(String.valueOf(days));
        this.maxStatesText.setText(prefs
                .getDefaultString(ResourcesPlugin.PREF_MAX_FILE_STATES));
        this.maxStateSizeText.setText(String.valueOf(megabytes));
        checkState();
    }

    /** 
     * Perform the result of the OK from the receiver.
     */
    public boolean performOk() {

        long longevityValue = validateLongTextEntry(longevityText);
        int maxFileStates = validateMaxFileStates();
        long maxStateSize = validateMaxFileStateSize();
        if (longevityValue == FAILED_VALUE || maxFileStates == FAILED_VALUE
                || maxStateSize == FAILED_VALUE)
            return false;

        IWorkspaceDescription description = getWorkspaceDescription();
        description.setFileStateLongevity(longevityValue * DAY_LENGTH);
        description.setMaxFileStates(maxFileStates);
        description.setMaxFileStateSize(maxStateSize * MEGABYTES);

        try {
            //As it is only a copy save it back in
            ResourcesPlugin.getWorkspace().setDescription(description);
        } catch (CoreException exception) {
            ErrorDialog.openError(getShell(), IDEWorkbenchMessages.FileHistory_exceptionSaving, exception
                    .getMessage(), exception.getStatus());
            return false;
        }

        return true;

    }

    /**
     * Validate a text entry for an integer field. Return the result if there are
     * no errors, otherwise return -1 and set the entry field error. 
     * @return int
     */
    private int validateIntegerTextEntry(Text text) {

        int value;

        try {
            value = Integer.parseInt(text.getText());

        } catch (NumberFormatException exception) {
            setErrorMessage(MessageFormat.format(IDEWorkbenchMessages.FileHistory_invalid,
                    new Object[] { exception.getLocalizedMessage() }));
            return FAILED_VALUE;
        }

        //Be sure all values are non zero and positive
        if (value <= 0) {
            setErrorMessage(IDEWorkbenchMessages.FileHistory_mustBePositive);
            return FAILED_VALUE;
        }

        return value;
    }

    /**
     * Validate a text entry for a long field. Return the result if there are
     * no errors, otherwise return -1 and set the entry field error. 
     * @return long
     */
    private long validateLongTextEntry(Text text) {

        long value;

        try {
            value = Long.parseLong(text.getText());

        } catch (NumberFormatException exception) {
            setErrorMessage(MessageFormat.format(IDEWorkbenchMessages.FileHistory_invalid,
                    new Object[] { exception.getLocalizedMessage() }));
            return FAILED_VALUE;
        }

        //Be sure all values are non zero and positive
        if (value <= 0) {
            setErrorMessage(IDEWorkbenchMessages.FileHistory_mustBePositive);
            return FAILED_VALUE;
        }

        return value;
    }

    /**
     * Validate the maximum file states.
     * Return the value if successful, otherwise
     * return FAILED_VALUE.
     * Set the error message if it fails.
     * @return int
     */
    private int validateMaxFileStates() {
        int maxFileStates = validateIntegerTextEntry(this.maxStatesText);
        if (maxFileStates == FAILED_VALUE)
            return maxFileStates;

        if (maxFileStates > FILE_STATES_MAXIMUM) {
            setErrorMessage(NLS.bind(IDEWorkbenchMessages.FileHistory_aboveMaxEntries, String.valueOf(FILE_STATES_MAXIMUM)));
            return FAILED_VALUE;
        }

        return maxFileStates;
    }

    /**
     * Validate the maximum file state size.
     * Return the value if successful, otherwise
     * return FAILED_VALUE.
     * Set the error message if it fails.
     * @return long
     */
    private long validateMaxFileStateSize() {
        long maxFileStateSize = validateLongTextEntry(this.maxStateSizeText);
        if (maxFileStateSize == FAILED_VALUE)
            return maxFileStateSize;

        if (maxFileStateSize > STATE_SIZE_MAXIMUM) {
            setErrorMessage(NLS.bind(IDEWorkbenchMessages.FileHistory_aboveMaxFileSize, String.valueOf(STATE_SIZE_MAXIMUM)));
            return FAILED_VALUE;
        }

        return maxFileStateSize;
    }

}
