/*
 * Copyright 2000-2009 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.refactoring.move.moveFilesOrDirectories;

import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.impl.file.JavaDirectoryServiceImpl;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.refactoring.move.MoveCallback;
import com.intellij.util.ArrayUtilRt;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;

public class JavaMoveFilesOrDirectoriesHandler extends MoveFilesOrDirectoriesHandler {
  @Override
  public PsiElement adjustTargetForMove(DataContext dataContext, PsiElement targetContainer) {
    if (targetContainer instanceof PsiPackage) {
      final Module module = LangDataKeys.TARGET_MODULE.getData(dataContext);
      if (module != null) {
        final PsiDirectory[] directories = ((PsiPackage)targetContainer).getDirectories(GlobalSearchScope.moduleScope(module));
        if (directories.length == 1) {
          return directories[0];
        }
      }
    }
    return super.adjustTargetForMove(dataContext, targetContainer);
  }

  @Override
  public PsiElement[] adjustForMove(Project project, PsiElement[] sourceElements, PsiElement targetElement) {
    sourceElements = super.adjustForMove(project, sourceElements, targetElement);
    if (sourceElements == null) {
      return null;
    }

    Set<PsiElement> result = new LinkedHashSet<PsiElement>();
    for (PsiElement sourceElement : sourceElements) {
      result.add(sourceElement instanceof PsiClass ? sourceElement.getContainingFile() : sourceElement);
    }
    return PsiUtilCore.toPsiElementArray(result);
  }

  @Override
  public void doMove(final Project project, PsiElement[] elements, PsiElement targetContainer, MoveCallback callback) {

    elements = super.adjustForMove(project, elements, targetContainer);
    if (elements == null) {
      return;
    }
    MoveFilesOrDirectoriesUtil
      .doMove(project, elements, new PsiElement[]{targetContainer}, callback, new Function<PsiElement[], PsiElement[]>() {
        @Override
        public PsiElement[] fun(final PsiElement[] elements) {
          return new WriteCommandAction<PsiElement[]>(project, "Regrouping ...") {
            @Override
            protected void run(Result<PsiElement[]> result) throws Throwable {
              final List<PsiElement> adjustedElements = new ArrayList<PsiElement>();
              for (int i = 0, length = elements.length; i < length; i++) {
                PsiElement element = elements[i];
                if (element instanceof PsiClass) {
                  final PsiClass topLevelClass = PsiUtil.getTopLevelClass(element);
                  if (topLevelClass != null) {
                    elements[i] = topLevelClass;
                    final PsiFile containingFile = obtainContainingFile(topLevelClass, elements);
                    if (containingFile != null && !adjustedElements.contains(containingFile)) {
                      adjustedElements.add(containingFile);
                      continue;
                    }
                  }
                }
                adjustedElements.add(element);
              }
              result.setResult(PsiUtilCore.toPsiElementArray(adjustedElements));
            }
          }.execute().getResultObject();
        }
      });
  }

  @Nullable
  private static PsiFile obtainContainingFile(@NotNull PsiElement element, PsiElement[] elements) {
    final PsiFile containingFile = element.getContainingFile();
    final PsiClass[] classes = ((PsiClassOwner)containingFile).getClasses();
    final Set<PsiClass> nonMovedClasses = new HashSet<PsiClass>();
    for (PsiClass aClass : classes) {
      if (ArrayUtilRt.find(elements, aClass) < 0) {
        nonMovedClasses.add(aClass);
      }
    }
    if (nonMovedClasses.isEmpty()) {
      return containingFile;
    }
    else {
      final PsiDirectory containingDirectory = containingFile.getContainingDirectory();
      if (containingDirectory != null) {
        try {
          JavaDirectoryServiceImpl.checkCreateClassOrInterface(containingDirectory, ((PsiClass)element).getName());
          final PsiElement createdClass = containingDirectory.add(element);
          element.delete();
          return createdClass.getContainingFile();
        }
        catch (IncorrectOperationException e) {
          final Iterator<PsiClass> iterator = nonMovedClasses.iterator();
          final PsiClass nonMovedClass = iterator.next();
          final PsiElement createdFile = containingDirectory.add(nonMovedClass).getContainingFile();
          nonMovedClass.delete();
          while (iterator.hasNext()) {
            final PsiClass currentClass = iterator.next();
            createdFile.add(currentClass);
            currentClass.delete();
          }
          return containingFile;
        }
      }
    }
    return null;
  }
}
