/*
 * User: anna
 * Date: 06-May-2008
 */
package com.intellij.refactoring;

import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.refactoring.replaceConstructorWithBuilder.ParameterData;
import com.intellij.refactoring.replaceConstructorWithBuilder.ReplaceConstructorWithBuilderProcessor;
import com.intellij.util.containers.HashMap;

import java.util.Map;

public class ReplaceConstructorWithBuilderTest extends MultiFileTestCase {

  public void testVarargs() throws Exception {
    doTest(true);
  }

  public void testExistingEmptyBuilder() throws Exception {
    doTest(false);
  }

  public void testMultipleParams() throws Exception {
    doTest(true);
  }

  public void testExistingHalfEmptyBuilder() throws Exception {
    doTest(false);
  }

  public void testExistingVoidSettersBuilder() throws Exception {
    doTest(false);
  }

  public void testConstructorChain() throws Exception {
    final HashMap<String, String> defaults = new HashMap<String, String>();
    defaults.put("i", "2");
    doTest(true, defaults);
  }

  public void testConstructorTree() throws Exception {
    doTest(true, null, "Found constructors are not reducible to simple chain");
  }

  private void doTest(final boolean createNewBuilderClass) throws Exception {
    doTest(createNewBuilderClass, null);
  }

  private void doTest(final boolean createNewBuilderClass, final Map<String, String> expectedDefaults) throws Exception {
    doTest(createNewBuilderClass, expectedDefaults, null);
  }

  private void doTest(final boolean createNewBuilderClass, final Map<String, String> expectedDefaults, final String conflicts) throws Exception {
    doTest(new PerformAction() {
      public void performAction(final VirtualFile rootDir, final VirtualFile rootAfter) throws Exception {
        final PsiClass aClass = myJavaFacade.findClass("Test", GlobalSearchScope.projectScope(getProject()));
        assertNotNull("Class Test not found", aClass);

        final HashMap<String, ParameterData> map = new HashMap<String, ParameterData>();
        final PsiMethod[] constructors = aClass.getConstructors();
        for (PsiMethod constructor : constructors) {
          ParameterData.createFromConstructor(constructor, map);
        }
        if (expectedDefaults != null) {
          for (Map.Entry<String, String> entry : expectedDefaults.entrySet()) {
            final ParameterData parameterData = map.get(entry.getKey());
            assertNotNull(parameterData);
            assertEquals(entry.getValue(), parameterData.getDefaultValue());
          }
        }
        try {
          new ReplaceConstructorWithBuilderProcessor(getProject(), constructors, map, "Builder", "", createNewBuilderClass).run();
          if (conflicts != null) {
            fail("Conflicts were not detected:" + conflicts);
          }
        }
        catch (Exception e) {

          if (conflicts == null) {
            fail("Conflict detected:" + e.getMessage());
          }
        }
        LocalFileSystem.getInstance().refresh(false);
        FileDocumentManager.getInstance().saveAllDocuments();
      }
    });
  }


  protected String getTestRoot() {
    return "/refactoring/replaceConstructorWithBuilder/";
  }
}

@@ -568,16 +568,48 @@
 shMap;%0A%0A
+import java.util.LinkedHashMap;%0A
 import j
@@ -2209,32 +2209,38 @@
 %0A%0A        final 
+Linked
 HashMap%3CString, 
@@ -2260,24 +2260,30 @@
 %3E map = new 
+Linked
 HashMap%3CStri

test fixed: predictable setters/fields order