/*
 * Copyright 2000-2011 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.intellij.framework.addSupport.impl;

import com.intellij.CommonBundle;
import com.intellij.facet.impl.ui.libraries.LibraryCompositionSettings;
import com.intellij.framework.FrameworkTypeEx;
import com.intellij.framework.addSupport.FrameworkSupportInModuleConfigurable;
import com.intellij.framework.addSupport.FrameworkSupportInModuleProvider;
import com.intellij.ide.util.frameworkSupport.FrameworkSupportModelImpl;
import com.intellij.ide.util.newProjectWizard.FrameworkSupportOptionsComponent;
import com.intellij.ide.util.newProjectWizard.impl.FrameworkSupportModelBase;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.ProjectBundle;
import com.intellij.openapi.roots.LibraryOrderEntry;
import com.intellij.openapi.roots.ModifiableModelsProvider;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.OrderEntry;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.ui.configuration.libraries.CustomLibraryDescription;
import com.intellij.openapi.roots.ui.configuration.libraries.LibraryPresentationManager;
import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainer;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Disposer;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @author nik
 */
public class AddSupportForSingleFrameworkDialog extends DialogWrapper {
  private final Module myModule;
  private final FrameworkSupportInModuleConfigurable myConfigurable;
  private final FrameworkSupportModelBase myModel;
  private final FrameworkSupportOptionsComponent myComponent;
  private final FrameworkTypeEx myFrameworkType;
  private final ModifiableModelsProvider myModifiableModelsProvider;

  public AddSupportForSingleFrameworkDialog(@NotNull Module module,
                                            final @NotNull String contentRootPath,
                                            FrameworkTypeEx frameworkType, @NotNull FrameworkSupportInModuleProvider provider,
                                            @NotNull LibrariesContainer librariesContainer,
                                            ModifiableModelsProvider modifiableModelsProvider) {
    super(module.getProject(), true);
    myFrameworkType = frameworkType;
    myModifiableModelsProvider = modifiableModelsProvider;
    setTitle(ProjectBundle.message("dialog.title.add.framework.0.support", frameworkType.getPresentableName()));
    myModule = module;
    myModel = new FrameworkSupportModelImpl(module.getProject(), contentRootPath, librariesContainer);
    myConfigurable = provider.createConfigurable(myModel);
    myComponent = new FrameworkSupportOptionsComponent(myModel, myModel.getLibrariesContainer(), myDisposable, myConfigurable, null);
    Disposer.register(myDisposable, myConfigurable);
    init();
  }

  protected void doOKAction() {
    final LibraryCompositionSettings librarySettings = myComponent.getLibraryCompositionSettings();
    if (librarySettings != null) {
      final ModifiableRootModel modifiableModel = myModifiableModelsProvider.getModuleModifiableModel(myModule);
      if (!askAndRemoveDuplicatedLibraryEntry(modifiableModel, librarySettings.getLibraryDescription())) {
        if (myConfigurable.isOnlyLibraryAdded()) {
          myModifiableModelsProvider.disposeModuleModifiableModel(modifiableModel);
          return;
        }
      }
      myModifiableModelsProvider.commitModuleModifiableModel(modifiableModel);

      final boolean downloaded = librarySettings.downloadFiles(getRootPane());
      if (!downloaded) {
        int answer = Messages.showYesNoDialog(getRootPane(),
                                              ProjectBundle.message("warning.message.some.required.libraries.wasn.t.downloaded"),
                                              CommonBundle.getWarningTitle(), Messages.getWarningIcon());
        if (answer != 0) {
          return;
        }
      }
    }

    new WriteAction() {
      protected void run(final Result result) {
        final ModifiableRootModel rootModel = myModifiableModelsProvider.getModuleModifiableModel(myModule);
        if (librarySettings != null) {
          librarySettings.addLibraries(rootModel, new ArrayList<Library>(), myModel.getLibrariesContainer());
        }
        myConfigurable.addSupport(myModule, rootModel, myModifiableModelsProvider);
        myModifiableModelsProvider.commitModuleModifiableModel(rootModel);
      }
    }.execute();
    super.doOKAction();
  }

  @Override
  protected String getDimensionServiceKey() {
    return "#com.intellij.framework.addSupport.AddSupportForSingleFrameworkDialog";
  }

  @Override
  protected String getHelpId() {
    return "reference.frameworks.support.dialog";//todo[nik]
  }

  protected JComponent createCenterPanel() {
    return myComponent.getMainPanel();
  }

  private boolean askAndRemoveDuplicatedLibraryEntry(@NotNull ModifiableRootModel rootModel, @NotNull CustomLibraryDescription description) {
    List<OrderEntry> existingEntries = new ArrayList<OrderEntry>();
    final LibrariesContainer container = myModel.getLibrariesContainer();
    for (OrderEntry entry : rootModel.getOrderEntries()) {
      if (!(entry instanceof LibraryOrderEntry)) continue;
      final Library library = ((LibraryOrderEntry)entry).getLibrary();
      if (library == null) continue;

      if (LibraryPresentationManager.getInstance().isLibraryOfKind(library, container, description.getSuitableLibraryKinds())) {
        existingEntries.add(entry);
      }
    }

    if (!existingEntries.isEmpty()) {
      String message;
      if (existingEntries.size() > 1) {
        message = "There are already " + existingEntries.size() + " " + myFrameworkType.getPresentableName() + " libraries.\n Do you want to replace they?";
      }
      else {
        final String name = existingEntries.get(0).getPresentableName();
        message = "There is already a " + myFrameworkType.getPresentableName() + " library '" + name + "'.\n Do you want to replace it?";
      }
      final int result = Messages.showYesNoCancelDialog(rootModel.getProject(), message, "Library Already Exists",
                                                        "&Replace", "&Add", "&Cancel", null);
      if (result == 0) {
        for (OrderEntry entry : existingEntries) {
          rootModel.removeOrderEntry(entry);
        }
      }
      else if (result != 1) {
        return false;
      }
    }
    return true;
  }
}

@@ -4223,32 +4223,48 @@
 turn;%0A        %7D%0A
+        return;%0A
       %7D%0A      my

add support: do not close dialog with support if user cancel suggestion to reuse library even if some addition actions are to be performed (IDEA-90953)