package jetbrains.mps.ide.refactoring;

/*Generated by MPS */

import jetbrains.mps.ide.platform.refactoring.RenameDialog;
import jetbrains.mps.project.AbstractModule;
import jetbrains.mps.project.MPSProject;
import javax.swing.JPanel;
import java.awt.HeadlessException;
import jetbrains.mps.ide.IdeBundle;
import org.jetbrains.annotations.Nullable;
import javax.lang.model.SourceVersion;
import jetbrains.mps.baseLanguage.closures.runtime.Wrappers;
import org.jetbrains.mps.openapi.module.SModule;
import java.util.function.Consumer;
import jetbrains.mps.refactoring.Renamer;
import jetbrains.mps.messages.IMessageHandler;
import jetbrains.mps.ide.messages.DefaultMessageHandler;
import jetbrains.mps.messages.Message;
import jetbrains.mps.messages.MessageKind;
import javax.swing.JComponent;
import com.intellij.ui.components.JBPanel;
import java.awt.BorderLayout;
import javax.swing.JLabel;
import com.intellij.ui.components.JBLabel;
import com.intellij.util.ui.JBUI;

public class RenameModuleDialog extends RenameDialog {
  private final AbstractModule myModule;
  private final MPSProject myProject;
  private JPanel myOptionsPanel;

  public RenameModuleDialog(MPSProject project, AbstractModule module) throws HeadlessException {
    super(project.getProject(), module.getModuleName(), "module");
    myModule = module;
    myProject = project;
    updateCentralPanel();
    setTitle(IdeBundle.message("actions.module.rename.title"));
    setResizable(true);
  }

  @Nullable
  @Override
  protected String checkValue() {
    final String fqName = getCurrentValue();
    if (fqName.isBlank()) {
      return "Invalid namespace";
    }

    if (!(Character.isJavaIdentifierStart(fqName.charAt(0)))) {
      return String.format("Namespace can't start with '%c'", fqName.charAt(0));
    }
    if (!(Character.isJavaIdentifierPart(fqName.charAt(fqName.length() - 1)))) {
      return String.format("Namespace can't end with '%c'", fqName.charAt(fqName.length() - 1));
    }

    if (!(SourceVersion.isName(fqName))) {
      return "Module namespace should be a valid Java package";
    }

    final Wrappers._T<String> checkResult = new Wrappers._T<String>(null);
    myProject.getRepository().getModelAccess().runReadAction(() -> {
      for (final SModule module : myProject.getRepository().getModules()) {
        if (module.equals(myModule)) {
          continue;
        }

        // module.getModuleName() can be null
        if (fqName.equals(module.getModuleName())) {
          checkResult.value = IdeBundle.message("actions.module.rename.name.in.repository");
          break;
        }
      }
    });

    return checkResult.value;
  }

  @Override
  protected void doRefactoringAction() {
    final String newModuleName = getCurrentValue();
    Consumer<Renamer.RenameProblem> msgConsumer = new Consumer<Renamer.RenameProblem>() {
      private final IMessageHandler msgHandler = new DefaultMessageHandler(myProject.getProject());

      @Override
      public void accept(Renamer.RenameProblem p) {
        Message msg;
        if (p.getSeverity() == Renamer.RenameProblem.Severity.CRITICAL) {
          msg = new Message(MessageKind.ERROR, RenameModuleDialog.class, p.getPresentation());
        } else if (p.getSeverity() == Renamer.RenameProblem.Severity.NON_CRITICAL) {
          msg = new Message(MessageKind.WARNING, RenameModuleDialog.class, p.getPresentation());
        } else {
          msg = new Message(MessageKind.INFORMATION, RenameModuleDialog.class, p.getPresentation());
        }
        msgHandler.handle(msg);
      }
    };
    final Renamer rr = new Renamer(myProject, myModule, msgConsumer);
    myProject.getModelAccess().runReadAction(() -> rr.collectRenames());
    rr.prepareRename(newModuleName);
    if (rr.hasPrimaryRename() || rr.hasDependantRenames()) {
      rr.runRenameCommand();
    }
    RenameModuleDialog.super.doRefactoringAction();
  }


  @Nullable
  @Override
  protected JComponent createCenterPanel() {
    myOptionsPanel = new JBPanel<JBPanel>(new BorderLayout());
    return myOptionsPanel;
  }


  /**
   * Have to update info panel after initialization in {@link jetbrains.mps.ide.refactoring.RenameModuleDialog#createCenterPanel() }, because last one happens in super constructor before {@link jetbrains.mps.ide.refactoring.RenameModuleDialog#myModule } is set.
   * i.e. infamous init() in cons call design defect. Perhaps, shall not use RenameDialog superclass?
   */
  private void updateCentralPanel() {
    final Renamer r = new Renamer(myProject, myModule, null);
    myProject.getModelAccess().runReadAction(() -> r.collectRenames());

    if (r.hasDependantRenames()) {
      JLabel label = new JBLabel(r.getDependantRenamesHTML(), JBLabel.LEFT);
      label.setBorder(JBUI.Borders.emptyLeft(2));
      myOptionsPanel.add(label, BorderLayout.NORTH);
    }
  }
}
