/*
 * 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.execution.testframework.sm;

import com.intellij.navigation.ChooseByNameContributor;
import com.intellij.navigation.NavigationItem;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.ex.temp.TempFileSystem;
import com.intellij.psi.PsiFile;
import com.intellij.util.text.StringTokenizer;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

/**
 * @author Roman Chernyatchik
 */
public class TestsLocationProviderUtil {
  @NonNls private static final String PROTOCOL_SEPARATOR = "://";
  private static final int MIN_PROXIMITY_THRESHOLD = 1;

  private TestsLocationProviderUtil() {
  }

  @Nullable
  public static String extractPath(@NotNull final String locationUrl) {
    final int index = locationUrl.indexOf(PROTOCOL_SEPARATOR);
    if (index >= 0) {
      return locationUrl.substring(index + PROTOCOL_SEPARATOR.length());
    }
    return null;
  }

  public static List<VirtualFile> findSuitableFilesFor(final String filePath, final Project project) {
    final ProjectFileIndex index = ProjectRootManager.getInstance(project).getFileIndex();

    // at first let's try to find file as is, by it's real path
    // and check that file belongs to current project
    // this location provider designed for tests thus we will check only project content
    // (we cannot check just sources or tests folders because RM doesn't use it
    final VirtualFile file = getByFullPath(filePath);
    final boolean inProjectContent = file != null && (index.isInContent(file));

    if (inProjectContent) {
      return Collections.singletonList(file);
    }

    //split file by "/" in parts
    final LinkedList<String> folders = new LinkedList<String>();
    final StringTokenizer st = new StringTokenizer(filePath, "/", false);
    String fileName = null;
    while (st.hasMoreTokens()) {
      final String pathComponent = st.nextToken();
      if (st.hasMoreTokens()) {
        folders.addFirst(pathComponent);
      } else {
        // last token
        fileName = pathComponent;
      }
    }
    if (fileName == null) {
      return Collections.emptyList();
    }
    return findFilesClosestToTarget(folders, collectCandidates(project, fileName, true), MIN_PROXIMITY_THRESHOLD);
  }

  /**
   * Looks for files with given name which are close to given path
   * @param targetParentFolders folders path
   * @param candidates
   * @param minProximityThreshold
   * @return
   */
  public static List<VirtualFile> findFilesClosestToTarget(@NotNull final List<String> targetParentFolders,
                                                           final List<FileInfo> candidates,
                                                           final int minProximityThreshold) {
    // let's find all files with similar relative path

    if (candidates.isEmpty()) {
      return Collections.emptyList();
    }

    // let's iterate relative path components and determine which files are closer to our relative path
    for (String folderName : targetParentFolders) {
      for (FileInfo info : candidates) {
        info.processRelativePathComponent(folderName);
      }
    }

    // let's extract the closest files to relative path. For this we will find max proximity and  and
    // we also assume that relative files and folders should have at least one common parent folder - just
    // to remove false positives on some cases
    int maxProximity = 0;
    for (FileInfo fileInfo : candidates) {
      final int proximity = fileInfo.getProximity();
      if (proximity > maxProximity) {
        maxProximity = proximity;
      }
    }

    if (maxProximity >= minProximityThreshold) {
      final List<VirtualFile> files = new ArrayList<VirtualFile>();
      for (FileInfo info : candidates) {
        if (info.getProximity() == maxProximity) {
          files.add(info.getFile());
        }
      }
      return files;
    }

    return Collections.emptyList();
  }

  public static List<FileInfo> collectCandidates(final Project project, final String fileName,
                                                 final boolean includeNonProjectItems) {
    final List<FileInfo> filesInfo = new ArrayList<FileInfo>();
    final ChooseByNameContributor[] contributors = Extensions.getExtensions(ChooseByNameContributor.FILE_EP_NAME);
    for (ChooseByNameContributor contributor : contributors) {
      // let's find files with same name in project and libraries
      final NavigationItem[] navigationItems = contributor.getItemsByName(fileName, fileName, project, includeNonProjectItems);
      for (NavigationItem navigationItem : navigationItems) {
        if (navigationItem instanceof PsiFile) {
          final VirtualFile itemFile = ((PsiFile)navigationItem).getVirtualFile();
          assert itemFile != null;

          filesInfo.add(new FileInfo(itemFile));
        }
      }
    }
    return filesInfo;
  }

  @Nullable
  private static VirtualFile getByFullPath(String filePath) {
    final VirtualFile fileByPath = LocalFileSystem.getInstance().findFileByPath(filePath);
    if (fileByPath != null) {
      return fileByPath;
    }
    // if we are in UnitTest mode probably TempFileSystem is used instead of LocalFileSystem
    if (ApplicationManager.getApplication().isUnitTestMode()) {
      return TempFileSystem.getInstance().findFileByPath(filePath);
    }
    return null;
  }

  public static class FileInfo {
    private final VirtualFile myFile;
    private VirtualFile myCurrentFolder;
    private int myProximity = 0;

    public FileInfo(VirtualFile file) {
      myFile = file;
      myCurrentFolder = myFile.getParent();
    }

    public void processRelativePathComponent(final String folderName) {
      if (myCurrentFolder == null) {
        return;
      }

      if (!folderName.equals(myCurrentFolder.getName())) {
        // if one of path components differs - no sense in checking others
        myCurrentFolder = null;
        return;
      }

      // common folder was found, let's increase proximity degree and move to parent folder
      myProximity ++;
      myCurrentFolder = myCurrentFolder.getParent();
    }

    public VirtualFile getFile() {
      return myFile;
    }

    public int getProximity() {
      return myProximity;
    }
  }
}
