/*******************************************************************************
 * Copyright (c) 2000, 2018 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.ui.preferences;

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.Label;
import org.eclipse.swt.widgets.Text;

import org.eclipse.core.runtime.IStatus;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;

import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.layout.PixelConverter;

import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;

import org.eclipse.jdt.core.JavaCore;

import org.eclipse.jdt.internal.corext.util.Messages;

import org.eclipse.jdt.launching.JavaRuntime;

import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.dialogs.StatusInfo;
import org.eclipse.jdt.internal.ui.dialogs.StatusUtil;
import org.eclipse.jdt.internal.ui.wizards.IStatusChangeListener;


public class JavaBuildConfigurationBlock extends OptionsConfigurationBlock {

	private static final String SETTINGS_SECTION_NAME= "JavaBuildConfigurationBlock"; //$NON-NLS-1$

	private static final Key PREF_PB_MAX_PER_UNIT= getJDTCoreKey(JavaCore.COMPILER_PB_MAX_PER_UNIT);

	private static final Key PREF_RESOURCE_FILTER= getJDTCoreKey(JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER);
	private static final Key PREF_BUILD_INVALID_CLASSPATH= getJDTCoreKey(JavaCore.CORE_JAVA_BUILD_INVALID_CLASSPATH);
	private static final Key PREF_BUILD_CLEAN_OUTPUT_FOLDER= getJDTCoreKey(JavaCore.CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER);
	private static final Key PREF_ENABLE_EXCLUSION_PATTERNS= getJDTCoreKey(JavaCore.CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS);
	private static final Key PREF_ENABLE_MULTIPLE_OUTPUT_LOCATIONS= getJDTCoreKey(JavaCore.CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS);

	private static final Key PREF_PB_INCOMPLETE_BUILDPATH= getJDTCoreKey(JavaCore.CORE_INCOMPLETE_CLASSPATH);
	private static final Key PREF_PB_CIRCULAR_BUILDPATH= getJDTCoreKey(JavaCore.CORE_CIRCULAR_CLASSPATH);
	private static final Key PREF_PB_INCOMPATIBLE_JDK_LEVEL= getJDTCoreKey(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL);
	private static final Key PREF_PB_MAIN_ONLY_PROJECT_HAS_TEST_ONLY_DEPENDENCY= getJDTCoreKey(JavaCore.CORE_MAIN_ONLY_PROJECT_HAS_TEST_ONLY_DEPENDENCY);
	private static final Key PREF_PB_OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE= getJDTCoreKey(JavaCore.CORE_OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE);
	private static final Key PREF_PB_DUPLICATE_RESOURCE= getJDTCoreKey(JavaCore.CORE_JAVA_BUILD_DUPLICATE_RESOURCE);
	private static final Key PREF_RECREATE_MODIFIED_CLASS_FILES= getJDTCoreKey(JavaCore.CORE_JAVA_BUILD_RECREATE_MODIFIED_CLASS_FILES_IN_OUTPUT_FOLDER);

	private static final Key PREF_PB_STRICTLY_COMPATIBLE_JRE_NOT_AVAILABLE= getJDTLaunchingKey(JavaRuntime.PREF_STRICTLY_COMPATIBLE_JRE_NOT_AVAILABLE);
	private static final Key PREF_PB_COMPILER_COMPLIANCE_DOES_NOT_MATCH_JRE= getJDTLaunchingKey(JavaRuntime.PREF_COMPILER_COMPLIANCE_DOES_NOT_MATCH_JRE);


	// values
	private static final String ERROR= JavaCore.ERROR;
	private static final String WARNING= JavaCore.WARNING;
	private static final String INFO= JavaCore.INFO;
	private static final String IGNORE= JavaCore.IGNORE;

	private static final String ABORT= JavaCore.ABORT;
	private static final String CLEAN= JavaCore.CLEAN;

	private static final String ENABLED= JavaCore.ENABLED;
	private static final String DISABLED= JavaCore.DISABLED;

	private PixelConverter fPixelConverter;

	private IStatus fMaxNumberProblemsStatus, fResourceFilterStatus;

	public JavaBuildConfigurationBlock(IStatusChangeListener context, IProject project, IWorkbenchPreferenceContainer container) {
		super(context, project, getKeys(), container);
		fMaxNumberProblemsStatus= new StatusInfo();
		fResourceFilterStatus= new StatusInfo();
	}

	private static Key[] getKeys() {
		Key[] keys= new Key[] {
				PREF_PB_MAX_PER_UNIT, PREF_RESOURCE_FILTER, PREF_BUILD_INVALID_CLASSPATH, PREF_PB_INCOMPLETE_BUILDPATH, PREF_PB_CIRCULAR_BUILDPATH,
				PREF_BUILD_CLEAN_OUTPUT_FOLDER, PREF_PB_DUPLICATE_RESOURCE,
				PREF_PB_INCOMPATIBLE_JDK_LEVEL, PREF_PB_OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE, PREF_ENABLE_EXCLUSION_PATTERNS, PREF_ENABLE_MULTIPLE_OUTPUT_LOCATIONS, 
				PREF_RECREATE_MODIFIED_CLASS_FILES,	PREF_PB_STRICTLY_COMPATIBLE_JRE_NOT_AVAILABLE, PREF_PB_COMPILER_COMPLIANCE_DOES_NOT_MATCH_JRE, 
				PREF_PB_MAIN_ONLY_PROJECT_HAS_TEST_ONLY_DEPENDENCY
			};
		return keys;
	}


	/*
	 * @see org.eclipse.jface.preference.PreferencePage#createContents(Composite)
	 */
	@Override
	protected Control createContents(Composite parent) {
		fPixelConverter= new PixelConverter(parent);
		setShell(parent.getShell());

		Composite mainComp= new Composite(parent, SWT.NONE);
		mainComp.setFont(parent.getFont());
		GridLayout layout= new GridLayout();
		layout.marginHeight= 0;
		layout.marginWidth= 0;
		mainComp.setLayout(layout);

		Composite othersComposite= createBuildPathTabContent(mainComp);
		GridData gridData= new GridData(GridData.FILL, GridData.FILL, true, true);
		gridData.heightHint= fPixelConverter.convertHeightInCharsToPixels(20);
		othersComposite.setLayoutData(gridData);

		validateSettings(null, null, null);

		return mainComp;
	}


	private Composite createBuildPathTabContent(Composite parent) {
		String[] abortIgnoreValues= new String[] { ABORT, IGNORE };
		String[] cleanIgnoreValues= new String[] { CLEAN, IGNORE };
		String[] enableDisableValues= new String[] { ENABLED, DISABLED };
		String[] enableIgnoreValues= new String[] { ENABLED, IGNORE };

		String[] errorWarning= new String[] { ERROR, WARNING };

		String[] errorWarningLabels= new String[] {
			PreferencesMessages.JavaBuildConfigurationBlock_error,
			PreferencesMessages.JavaBuildConfigurationBlock_warning
		};

		String[] errorIgnore= new String[] { ERROR, IGNORE };

		String[] errorIgnoreLabels= new String[] {
			PreferencesMessages.JavaBuildConfigurationBlock_error,
			PreferencesMessages.JavaBuildConfigurationBlock_ignore
		};

		String[] errorWarningInfoIgnore= new String[] { ERROR, WARNING, INFO, IGNORE };
		String[] errorWarningInfoIgnoreLabels= new String[] {
			PreferencesMessages.JavaBuildConfigurationBlock_error,
			PreferencesMessages.JavaBuildConfigurationBlock_warning,
			PreferencesMessages.JavaBuildConfigurationBlock_info,
			PreferencesMessages.JavaBuildConfigurationBlock_ignore
		};

		int nColumns= 3;

		final ScrolledPageContent pageContent = new ScrolledPageContent(parent);

		GridLayout layout= new GridLayout();
		layout.numColumns= nColumns;
		layout.marginHeight= 0;
		layout.marginWidth= 0;

		Composite composite= pageContent.getBody();
		composite.setLayout(layout);

		String label= PreferencesMessages.JavaBuildConfigurationBlock_section_general;
		ExpandableComposite excomposite= createStyleSection(composite, label, nColumns);

		Composite othersComposite= new Composite(excomposite, SWT.NONE);
		excomposite.setClient(othersComposite);
		othersComposite.setLayout(new GridLayout(nColumns, false));

		label= PreferencesMessages.JavaBuildConfigurationBlock_pb_max_per_unit_label;
		Text text= addTextField(othersComposite, label, PREF_PB_MAX_PER_UNIT, 0, 0);
		GridData gd= (GridData) text.getLayoutData();
		gd.widthHint= fPixelConverter.convertWidthInCharsToPixels(8);
		gd.horizontalAlignment= GridData.END;
		text.setTextLimit(6);

		label= PreferencesMessages.JavaBuildConfigurationBlock_enable_exclusion_patterns_label;
		addCheckBox(othersComposite, label, PREF_ENABLE_EXCLUSION_PATTERNS, enableDisableValues, 0);

		label= PreferencesMessages.JavaBuildConfigurationBlock_enable_multiple_outputlocations_label;
		addCheckBox(othersComposite, label, PREF_ENABLE_MULTIPLE_OUTPUT_LOCATIONS, enableDisableValues, 0);

		label= PreferencesMessages.JavaBuildConfigurationBlock_section_build_path_problems;
		excomposite= createStyleSection(composite, label, nColumns);

		othersComposite= new Composite(excomposite, SWT.NONE);
		excomposite.setClient(othersComposite);
		othersComposite.setLayout(new GridLayout(nColumns, false));

		label= PreferencesMessages.JavaBuildConfigurationBlock_build_invalid_classpath_label;
		addCheckBox(othersComposite, label, PREF_BUILD_INVALID_CLASSPATH, abortIgnoreValues, 0);

		label= PreferencesMessages.JavaBuildConfigurationBlock_pb_incomplete_build_path_label;
		addComboBox(othersComposite, label, PREF_PB_INCOMPLETE_BUILDPATH, errorWarning, errorWarningLabels, 0);

		label= PreferencesMessages.JavaBuildConfigurationBlock_pb_build_path_cycles_label;
		addComboBox(othersComposite, label, PREF_PB_CIRCULAR_BUILDPATH, errorWarning, errorWarningLabels, 0);

		label= PreferencesMessages.JavaBuildConfigurationBlock_pb_check_prereq_binary_level_label;
		addComboBox(othersComposite, label, PREF_PB_INCOMPATIBLE_JDK_LEVEL, errorWarningInfoIgnore, errorWarningInfoIgnoreLabels, 0);
		
		label = PreferencesMessages.JavaBuildConfigurationBlock_pb_output_overlapping_with_source_label;
		addComboBox(othersComposite, label, PREF_PB_OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE, errorWarningInfoIgnore, errorWarningInfoIgnoreLabels, 0);

		label= PreferencesMessages.JavaBuildConfigurationBlock_pb_strictly_compatible_jre_not_available_label;
		addComboBox(othersComposite, label, PREF_PB_STRICTLY_COMPATIBLE_JRE_NOT_AVAILABLE, errorWarningInfoIgnore, errorWarningInfoIgnoreLabels, 0);

		label= PreferencesMessages.JavaBuildConfigurationBlock_pb_compiler_compliance_does_not_match_jre_label;
		addComboBox(othersComposite, label, PREF_PB_COMPILER_COMPLIANCE_DOES_NOT_MATCH_JRE, errorWarningInfoIgnore, errorWarningInfoIgnoreLabels, 0);

		label= PreferencesMessages.JavaBuildConfigurationBlock_pb_main_only_project_has_test_only_dependency_label;
		addComboBox(othersComposite, label, PREF_PB_MAIN_ONLY_PROJECT_HAS_TEST_ONLY_DEPENDENCY, errorIgnore, errorIgnoreLabels, 0);

		label= PreferencesMessages.JavaBuildConfigurationBlock_section_output_folder;
		excomposite= createStyleSection(composite, label, nColumns);

		othersComposite= new Composite(excomposite, SWT.NONE);
		excomposite.setClient(othersComposite);
		othersComposite.setLayout(new GridLayout(nColumns, false));

		label= PreferencesMessages.JavaBuildConfigurationBlock_pb_duplicate_resources_label;
		addComboBox(othersComposite, label, PREF_PB_DUPLICATE_RESOURCE, errorWarning, errorWarningLabels, 0);

		label= PreferencesMessages.JavaBuildConfigurationBlock_build_clean_outputfolder_label;
		addCheckBox(othersComposite, label, PREF_BUILD_CLEAN_OUTPUT_FOLDER, cleanIgnoreValues, 0);

		label= PreferencesMessages.JavaBuildConfigurationBlock_build_recreate_modified;
		addCheckBox(othersComposite, label, PREF_RECREATE_MODIFIED_CLASS_FILES, enableIgnoreValues, 0);

		label= PreferencesMessages.JavaBuildConfigurationBlock_resource_filter_label;
		text= addTextField(othersComposite, label, PREF_RESOURCE_FILTER, 0, 0);
		gd= (GridData) text.getLayoutData();
		gd.grabExcessHorizontalSpace= true;
		gd.widthHint= fPixelConverter.convertWidthInCharsToPixels(10);

		Label description= new Label(othersComposite, SWT.WRAP);
		description.setText(PreferencesMessages.JavaBuildConfigurationBlock_resource_filter_description);
		gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
		gd.horizontalSpan= nColumns;
		gd.widthHint= fPixelConverter.convertWidthInCharsToPixels(60);
		description.setLayoutData(gd);

		IDialogSettings section= JavaPlugin.getDefault().getDialogSettings().getSection(SETTINGS_SECTION_NAME);
		restoreSectionExpansionStates(section);

		return pageContent;
	}

	/* (non-javadoc)
	 * Update fields and validate.
	 * @param changedKey Key that changed, or null, if all changed.
	 */
	@Override
	protected void validateSettings(Key changedKey, String oldValue, String newValue) {
		if (!areSettingsEnabled()) {
			return;
		}

		if (changedKey != null) {
			if (PREF_PB_MAX_PER_UNIT.equals(changedKey)) {
				fMaxNumberProblemsStatus= validateMaxNumberProblems();
			} else if (PREF_RESOURCE_FILTER.equals(changedKey)) {
				fResourceFilterStatus= validateResourceFilters();
			} else {
				return;
			}
		} else {
			updateEnableStates();
			fMaxNumberProblemsStatus= validateMaxNumberProblems();
			fResourceFilterStatus= validateResourceFilters();
		}
		IStatus status= StatusUtil.getMostSevere(new IStatus[] { fMaxNumberProblemsStatus, fResourceFilterStatus });
		fContext.statusChanged(status);
	}

	private void updateEnableStates() {
	}

	@Override
	protected String[] getFullBuildDialogStrings(boolean workspaceSettings) {
		String title= PreferencesMessages.JavaBuildConfigurationBlock_needsbuild_title;
		String message;
		if (workspaceSettings) {
			message= PreferencesMessages.JavaBuildConfigurationBlock_needsfullbuild_message;
		} else {
			message= PreferencesMessages.JavaBuildConfigurationBlock_needsprojectbuild_message;
		}
		return new String[] { title, message };
	}

	private IStatus validateMaxNumberProblems() {
		String number= getValue(PREF_PB_MAX_PER_UNIT);
		StatusInfo status= new StatusInfo();
		if (number.length() == 0) {
			status.setError(PreferencesMessages.JavaBuildConfigurationBlock_empty_input);
		} else {
			try {
				int value= Integer.parseInt(number);
				if (value <= 0) {
					status.setError(Messages.format(PreferencesMessages.JavaBuildConfigurationBlock_invalid_input, number));
				}
			} catch (NumberFormatException e) {
				status.setError(Messages.format(PreferencesMessages.JavaBuildConfigurationBlock_invalid_input, number));
			}
		}
		return status;
	}

	private IStatus validateResourceFilters() {
		String text= getValue(PREF_RESOURCE_FILTER);

		IWorkspace workspace= ResourcesPlugin.getWorkspace();

		String[] filters= getTokens(text, ","); //$NON-NLS-1$
		for (int i= 0; i < filters.length; i++) {
			String fileName= filters[i].replace('*', 'x');
			int resourceType= IResource.FILE;
			int lastCharacter= fileName.length() - 1;
			if (lastCharacter >= 0 && fileName.charAt(lastCharacter) == '/') {
				fileName= fileName.substring(0, lastCharacter);
				resourceType= IResource.FOLDER;
			}
			IStatus status= workspace.validateName(fileName, resourceType);
			if (status.matches(IStatus.ERROR)) {
				String message= Messages.format(PreferencesMessages.JavaBuildConfigurationBlock_filter_invalidsegment_error, status.getMessage());
				return new StatusInfo(IStatus.ERROR, message);
			}
		}
		return new StatusInfo();
	}

	@Override
	public void dispose() {
		IDialogSettings settings= JavaPlugin.getDefault().getDialogSettings().addNewSection(SETTINGS_SECTION_NAME);
		storeSectionExpansionStates(settings);
		super.dispose();
	}


}
