package com.intellij.openapi.vcs.changes;

import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;

import java.io.File;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;

public class IgnoredFilesComponent {
  private final Project myProject;
  private final Set<IgnoredFileBean> myFilesToIgnore;

  public IgnoredFilesComponent(final Project project) {
    myProject = project;
    myFilesToIgnore = new HashSet<IgnoredFileBean>();
  }

  public void add(final IgnoredFileBean... filesToIgnore) {
    synchronized(myFilesToIgnore) {
      Collections.addAll(myFilesToIgnore, filesToIgnore);
    }
  }

  public void clear() {
    synchronized (myFilesToIgnore) {
      myFilesToIgnore.clear();
    }
  }
  public boolean isEmpty() {
    synchronized (myFilesToIgnore) {
      return myFilesToIgnore.isEmpty();
    }
  }

  public void set(final IgnoredFileBean... filesToIgnore) {
    synchronized(myFilesToIgnore) {
      myFilesToIgnore.clear();
      Collections.addAll(myFilesToIgnore, filesToIgnore);
    }
  }

  public IgnoredFileBean[] getFilesToIgnore() {
    synchronized(myFilesToIgnore) {
      return myFilesToIgnore.toArray(new IgnoredFileBean[myFilesToIgnore.size()]);
    }
  }

  public static enum IgnoreResult {
    NO,
    SELF,
    SUBTREE
  }

  public boolean isIgnoredFile(@NotNull VirtualFile file) {
    return ! IgnoreResult.NO.equals(isIgnoredFileWithType(file));
  }

  public IgnoreResult isIgnoredFileWithType(@NotNull VirtualFile file) {
    synchronized(myFilesToIgnore) {
      if (myFilesToIgnore.size() == 0) {
        return IgnoreResult.NO;
      }
      String filePath = null;
      // don't use VfsUtil.getRelativePath() here because it can't handle paths where one file is not a direct ancestor of another one
      final VirtualFile baseDir = myProject.getBaseDir();
      final File baseDirIoFile = (baseDir != null) ? new File(baseDir.getPath()) : null;
      if (baseDir != null) {
        filePath = FileUtil.getRelativePath(new File(baseDir.getPath()), new File(file.getPath()));
        if (filePath != null) {
          filePath = FileUtil.toSystemIndependentName(filePath);
        }
        if (file.isDirectory()) {
          filePath += "/";
        }
      }
      String absIoPath = new File(file.getPath()).getAbsolutePath();
      absIoPath = file.isDirectory() ? (absIoPath + File.separatorChar) : absIoPath;
      for(IgnoredFileBean bean: myFilesToIgnore) {
        if (filePath != null) {
          final String prefix = bean.getPath();
          if ("./".equals(prefix)) {
            // special case for ignoring the project base dir (IDEADEV-16056)
            final String basePath = FileUtil.toSystemIndependentName(baseDir.getPath());
            final String fileAbsPath = FileUtil.toSystemIndependentName(file.getPath());
            if (StringUtil.startsWithIgnoreCase(fileAbsPath, basePath)) {
              return IgnoreResult.SUBTREE;
            }
          }
          else if (prefix != null && bean.fileIsUnderMe(absIoPath, baseDirIoFile)) {
            return IgnoreSettingsType.UNDER_DIR.equals(bean.getType()) ? IgnoreResult.SUBTREE : IgnoreResult.SELF;
          }
        }
        final Pattern pattern = bean.getPattern();
        if (pattern != null && pattern.matcher(file.getName()).matches()) {
          return IgnoreResult.SELF;
        }
      }
      return IgnoreResult.NO;
    }
  }
}

@@ -1818,38 +1818,8 @@
   %7D%0A
-      String filePath = null;%0A
     
@@ -2100,323 +2100,8 @@
 ll;%0A
-      if (baseDir != null) %7B%0A        filePath = FileUtil.getRelativePath(new File(baseDir.getPath()), new File(file.getPath()));%0A        if (filePath != null) %7B%0A          filePath = FileUtil.toSystemIndependentName(filePath);%0A        %7D%0A        if (file.isDirectory()) %7B%0A          filePath += %22/%22;%0A        %7D%0A      %7D%0A
     
@@ -2305,42 +2305,8 @@
 ) %7B%0A
-        if (filePath != null) %7B%0A  
     
@@ -2351,26 +2351,24 @@
 ();%0A        
-  
 if (%22./%22.equ
@@ -2378,22 +2378,39 @@
 (prefix)
+ && baseDir != null
 ) %7B%0A
-  
         
@@ -2477,18 +2477,16 @@
 -16056)%0A
-  
         
@@ -2566,34 +2566,32 @@
 h());%0A          
-  
 final String fil
@@ -2643,34 +2643,32 @@
 ile.getPath());%0A
-  
           if (St
@@ -2727,34 +2727,32 @@
 ) %7B%0A            
-  
 return IgnoreRes
@@ -2766,38 +2766,34 @@
 TREE;%0A          
- 
- 
 %7D%0A
-  
         %7D%0A      
@@ -2782,26 +2782,24 @@
 %7D%0A        %7D%0A
-  
         else
@@ -2871,34 +2871,32 @@
 e)) %7B%0A          
- 
- 
 return IgnoreSet
@@ -2982,28 +2982,16 @@
 t.SELF;%0A
-          %7D%0A
         

remove expensive and no longer necessary code