// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.execution.application;

import com.intellij.execution.ExecutionBundle;
import com.intellij.execution.configurations.RuntimeConfigurationException;
import com.intellij.execution.ui.*;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.ui.EditorTextField;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Collections;
import java.util.List;

import static com.intellij.execution.ui.CommandLinePanel.setMinimumWidth;

public final class JavaApplicationSettingsEditor extends JavaSettingsEditorBase<ApplicationConfiguration> {

  public JavaApplicationSettingsEditor(ApplicationConfiguration configuration) {
    super(configuration);
  }

  @Override
  public boolean isInplaceValidationSupported() {
    return true;
  }

  @Override
  protected void customizeFragments(List<SettingsEditorFragment<ApplicationConfiguration, ?>> fragments,
                                    SettingsEditorFragment<ApplicationConfiguration, ModuleClasspathCombo> moduleClasspath,
                                    CommonParameterFragments<ApplicationConfiguration> commonParameterFragments) {
    fragments.add(SettingsEditorFragment.createTag("include.provided",
                                                   ExecutionBundle.message("application.configuration.include.provided.scope"),
                                                   ExecutionBundle.message("group.java.options"),
                                     configuration -> configuration.getOptions().isIncludeProvidedScope(),
                                     (configuration, value) -> configuration.getOptions().setIncludeProvidedScope(value)));
    fragments.add(commonParameterFragments.programArguments());
    fragments.add(new TargetPathFragment<>());
    fragments.add(commonParameterFragments.createRedirectFragment());
    SettingsEditorFragment<ApplicationConfiguration, EditorTextField> mainClassFragment = createMainClass(moduleClasspath.component());
    fragments.add(mainClassFragment);
    DefaultJreSelector jreSelector = DefaultJreSelector.fromSourceRootsDependencies(moduleClasspath.component(), mainClassFragment.component());
    SettingsEditorFragment<ApplicationConfiguration, JrePathEditor> jrePath = CommonJavaFragments.createJrePath(jreSelector);
    fragments.add(jrePath);
    fragments.add(createShortenClasspath(moduleClasspath.component(), jrePath, true));
  }

  @NotNull
  private SettingsEditorFragment<ApplicationConfiguration, EditorTextField> createMainClass(ModuleClasspathCombo classpathCombo) {
    ConfigurationModuleSelector moduleSelector = new ConfigurationModuleSelector(getProject(), classpathCombo);
    EditorTextField mainClass = ClassEditorField.createClassField(getProject(), () -> classpathCombo.getSelectedModule(),
                                                                  ApplicationConfigurable.getVisibilityChecker(moduleSelector), null);
    mainClass.setBackground(UIUtil.getTextFieldBackground());
    mainClass.setShowPlaceholderWhenFocused(true);
    CommonParameterFragments.setMonospaced(mainClass);
    String placeholder = ExecutionBundle.message("application.configuration.main.class.placeholder");
    mainClass.setPlaceholder(placeholder);
    mainClass.getAccessibleContext().setAccessibleName(placeholder);
    setMinimumWidth(mainClass, 300);
    SettingsEditorFragment<ApplicationConfiguration, EditorTextField> mainClassFragment =
      new SettingsEditorFragment<>("mainClass", ExecutionBundle.message("application.configuration.main.class"), null, mainClass, 20,
                                   (configuration, component) -> component.setText(getQName(configuration.getMainClassName())),
                                   (configuration, component) -> configuration.setMainClassName(component.getText()),
                                   configuration -> true);
    mainClassFragment.setHint(ExecutionBundle.message("application.configuration.main.class.hint"));
    mainClassFragment.setRemovable(false);
    mainClassFragment.setEditorGetter(field -> {
      Editor editor = field.getEditor();
      return editor == null ? field : editor.getContentComponent();
    });
    mainClassFragment.setValidation((configuration) ->
      Collections.singletonList(RuntimeConfigurationException.validate(mainClass, () -> ReadAction.run(() -> configuration.checkClass()))));
    return mainClassFragment;
  }

  @Nullable
  private String getQName(@Nullable String className) {
    if (className == null) return null;
    PsiClass psiClass = JavaPsiFacade.getInstance(getProject()).findClass(className, GlobalSearchScope.allScope(getProject()));
    return psiClass == null ? className : psiClass.getQualifiedName();
  }
}

@@ -457,109 +457,36 @@
 lij.
-psi.JavaPsiFacade;%0Aimport com.intellij.psi.PsiClass;%0Aimport com.intellij.psi.search.GlobalSearchScope
+openapi.util.text.StringUtil
 ;%0Aim
@@ -604,51 +604,8 @@
 ull;
-%0Aimport org.jetbrains.annotations.Nullable;
 %0A%0Aim
@@ -3903,23 +3903,36 @@
 setText(
-getQNam
+StringUtil.notNulliz
 e(config
@@ -3958,16 +3958,41 @@
 sName())
+.replaceAll(%22%5C%5C$%22, %22%5C%5C.%22)
 ),%0A     
@@ -4706,319 +4706,7 @@
 %0A  %7D
-%0A%0A  @Nullable%0A  private String getQName(@Nullable String className) %7B%0A    if (className == null) return null;%0A    PsiClass psiClass = JavaPsiFacade.getInstance(getProject()).findClass(className, GlobalSearchScope.allScope(getProject()));%0A    return psiClass == null ? className : psiClass.getQualifiedName();%0A  %7D
 %0A%7D%0A

Revert "IDEA-261718 Application run configuration: inner class is prefixed with dollar and is reported invalid"