/*
 * Copyright 2008 Google Inc.
 *
 * 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.google.gwt.dev.resource.impl;

import com.google.gwt.thirdparty.apache.ant.types.ZipScanner;

import java.util.regex.Pattern;

/**
 * A singleton class that provides blazingly fast implementation of the default
 * excludes of Ant's {@link com.google.gwt.thirdparty.apache.ant.DirectoryScanner},
 * assuming case-sensitiveness.
 *
 * TODO: this class needs to be revisited, when Gwt's Ant is upgraded.
 *
 * Currently, we do not go to ant if (a) the filterList is empty, or (b) the
 * filterList has "common" patterns. Exception: When path ends in '/', we defer
 * to ant.
 *
 * TODO: This code could be made more general and cleaner by removing the
 * dependency on Ant completely. All ant patterns could be compiled into
 * reg-exps. That could also make the code faster. Plus, at several places,
 * Ant's documentation seems to be incomplete. Instead, perhaps, we should
 * specify our own rules for writing patterns.
 */
public class DefaultFilters {

  /**
   * Constants to represent the type of files that will be filtered.
   */
  public static enum FilterFileType {
    RESOURCE_FILES(null), //
    JAVA_FILES(".java"), //
    CLASS_FILES(".class");

    private final String suffix;

    /* used when defaultExcludes is false */
    private final ResourceFilter justThisFileTypeFilter = new ResourceFilter() {
      @Override
      public boolean allows(String path) {
        return defaultAntIncludes.allows(path) && matches(path);
      }
    };

    private final ResourceFilter defaultFilter = new ResourceFilter() {

      @Override
      public boolean allows(String path) {
        return getFileTypeFilter().allows(path)
        && !isDefaultExcluded(path);
      }
    };

    private FilterFileType(String suffix) {
      this.suffix = suffix;
    }

    public ResourceFilter getDefaultFilter() {
      return defaultFilter;
    }

    /* used when defaultExcludes is false */
    public ResourceFilter getFileTypeFilter() {
      return justThisFileTypeFilter;
    }

    public String getSuffix() {
      return suffix;
    }

    public boolean matches(String path) {
      if (suffix == null) {
        return true;
      }
      return path.endsWith(suffix);
    }
  }

  // \w (word character), ., $, /, -, *, ~, #, %
  private static final Pattern antPattern = Pattern.compile("^[\\w\\.\\$/\\-\\*~#%]*$");

  // accepts all but paths starting with '/'. Default include list is '**'
  private static final ResourceFilter defaultAntIncludes = new ResourceFilter() {
    @Override
    public boolean allows(String path) {
      return path.charAt(0) != '/';
    }
  };

  /**
   * @return <code>true</code> if given path should be excluded from resources.
   */
  private static boolean isDefaultExcluded(String path) {
    // CVS
    if (path.endsWith("/CVS") || path.contains("/CVS/") || path.startsWith("CVS/")
        || path.endsWith("/.cvsignore")) {
      return true;
    }
    // Subversion
    if (path.endsWith("/.svn") || path.contains("/.svn/") || path.startsWith(".svn/")
        || path.endsWith("/.svnignore")) {
      return true;
    }
    // Git
    if (path.endsWith("/.git") || path.contains("/.git/") || path.startsWith(".git/")
        || path.endsWith("/.gitignore")) {
      return true;
    }
    // SCCS
    if (path.endsWith("/SCCS") || path.contains("/SCCS/")) {
      return true;
    }
    // Visual SourceSafe
    if (path.endsWith("/vssver.scc")) {
      return true;
    }
    // Mac
    if (path.endsWith("/.DS_Store")) {
      return true;
    }
    return false;
  }

  /**
   * Returns a pattern string that can be passed in Java Pattern.compile(..).
   * For spec, see <a href="http://www.jajakarta.org/ant/ant-1.6.1/docs/ja/manual/api/org/apache/tools/ant/DirectoryScanner.html"
   * >DirectoryScanner</a> From the spec: There is a special case regarding the
   * use of File.separators at the beginning of the pattern and the string to
   * match: When a pattern starts with a File.separator, the string to match
   * must also start with a File.separator. When a pattern does not start with a
   * File.separator, the string to match may not start with a File.separator.
   *
   * </p>
   *
   * TODO: This method could accept all ant patterns, but then all characters
   * that have a special meaning in Java's regular expression would need to be
   * escaped.
   *
   * @param antPatternString the ant pattern String.
   * @return a pattern string that can be passed in Java's Pattern.compile(..),
   *         null if cannot process the pattern.
   */
  static String getPatternFromAntPattern(String antPatternString) {
    if (!antPattern.matcher(antPatternString).matches()) {
      return null;
    }
    // do not handle patterns that have ***
    if (antPatternString.indexOf("***") != -1) {
      return null;
    }
    if (antPatternString.endsWith("/")) {
      /*
       * From the DirectoryScanner.html spec: When a pattern ends with a '/' or
       * '\', "**" is appended. if ant pattern = testing/, path = testing/foo,
       * result = true.
       */
      antPatternString = antPatternString + "**";
    }
    StringBuilder sb = new StringBuilder();
    int length = antPatternString.length();
    for (int i = 0; i < length; i++) {
      char c = antPatternString.charAt(i);
      switch (c) {
        case '.':
          sb.append("\\.");
          break;
        case '$':
          sb.append("\\$");
          break;
        case '/':
          // convert /** to (/[^/]*)* except when / is the first char.
          if (i != 0 && i + 2 < length && antPatternString.charAt(i + 1) == '*'
              && antPatternString.charAt(i + 2) == '*') {
            sb.append("(/[^/]*)*");
            i += 2; // handled 2 more chars than usual
          } else {
            sb.append(c);
          }
          break;
        case '*':
          // ** to .*
          if (i + 1 < length && antPatternString.charAt(i + 1) == '*') {
            if (i + 2 < length && antPatternString.charAt(i + 2) == '/') {
              if (i == 0) {
                /*
                 * When a pattern does not start with a File.separator, the
                 * string to match may not start with a File.separator.
                 */
                sb.append("([^/]+/)*");
              } else {
                // convert **/ to ([^/]*/)*
                sb.append("([^/]*/)*");
              }
              i += 2;
            } else {
              if (i == 0) {
                /*
                 * When a pattern does not start with a File.separator, the
                 * string to match may not start with a File.separator.
                 */
                sb.append("([^/].*)*");
              } else {
                sb.append(".*");
              }
              i++;
            }
          } else {
            sb.append("[^/]*");
          }
          break;
        default:
          sb.append(c);
          break;
      }
    }
    return sb.toString();
  }

  static ZipScanner getScanner(String[] includeList, String[] excludeList,
      String[] skipList, boolean defaultExcludes, boolean caseSensitive) {
    /*
     * Hijack Ant's ZipScanner to handle inclusions/exclusions exactly as Ant
     * does. We're only using its pattern-matching capabilities; the code path
     * I'm using never tries to hit the filesystem in Ant 1.6.5.
     */
    ZipScanner scanner = new ZipScanner();
    if (includeList.length > 0) {
      scanner.setIncludes(includeList);
    }
    if (excludeList.length > 0 || skipList.length > 0) {
      String[] excludeOrSkip = concatenate(excludeList, skipList);
      scanner.setExcludes(excludeOrSkip);
    }
    if (defaultExcludes) {
      scanner.addDefaultExcludes();
    }
    scanner.setCaseSensitive(caseSensitive);
    scanner.init();

    return scanner;
  }

  private static String[] concatenate(String[] array1, String[] array2) {
    String[] answer = new String[array1.length + array2.length];
    int i = 0;
    for (String entry : array1) {
      answer[i++] = entry;
    }
    for (String entry : array2) {
      answer[i++] = entry;
    }
    return answer;
  }

  private static Pattern getPatternFromStrings(String... patterns) {
    StringBuilder entirePattern = new StringBuilder("^");
    int length = patterns.length;
    int count = 0;
    for (String pattern : patterns) {
      entirePattern.append("(" + pattern + ")");
      if (count < length - 1) {
        entirePattern.append("|");
      }
      count++;
    }
    entirePattern.append("$");
    return Pattern.compile(entirePattern.toString());
  }

  private final ResourceFilter rejectAll = new ResourceFilter() {
    @Override
    public boolean allows(String path) {
      return false;
    }
  };

  public ResourceFilter customClassFilesFilter(String includeList[],
      String excludeList[], String skipList[], boolean defaultExcludes,
      boolean caseSensitive) {
    return getCustomFilter(includeList, excludeList, skipList, defaultExcludes,
        caseSensitive, FilterFileType.CLASS_FILES);
  }

  public ResourceFilter customJavaFilter(String includeList[],
      String excludeList[], String skipList[], boolean defaultExcludes,
      boolean caseSensitive) {
    return getCustomFilter(includeList, excludeList, skipList, defaultExcludes,
        caseSensitive, FilterFileType.JAVA_FILES);
  }

  public ResourceFilter customResourceFilter(String includeList[],
      String excludeList[], String[] skipList, boolean defaultExcludes,
      boolean caseSensitive) {
    return getCustomFilter(includeList, excludeList, skipList, defaultExcludes,
        caseSensitive, FilterFileType.RESOURCE_FILES);
  }

  /**
   * Return a customResourceFiter that handles all the argument. If unable to
   * create a customResourceFilter that handles the arguments, catchAll is used
   * as the final ResourceFilter.
   */
  ResourceFilter customFilterWithCatchAll(final String includeList[],
      final String excludeList[], final String skipList[],
      final boolean defaultExcludes, final ResourceFilter catchAll,
      final FilterFileType filterFileType) {

    assert includeList.length > 0 || excludeList.length > 0
        || skipList.length > 0;

    final ResourceFilter includeFilter = getIncludesFilterPart(includeList);
    final ResourceFilter excludeFilter = getExcludesFilterPart(concatenate(
        excludeList, skipList));

    if (includeFilter == null || excludeFilter == null) {
      return catchAll;
    }
    // another common-case
    ResourceFilter filter = new ResourceFilter() {
      @Override
      public boolean allows(String path) {
        // do not handle the case when pattern ends in '/'
        if (path.endsWith("/")) {
          return catchAll.allows(path);
        }
        return isPathAllowedByDefaults(path, defaultExcludes, filterFileType)
            && includeFilter.allows(path) && !excludeFilter.allows(path);
      }

      private boolean isPathAllowedByDefaults(String path,
          boolean defaultExcludes, FilterFileType filterFileType) {
        boolean fileTypeMatch = filterFileType.matches(path);
        if (!fileTypeMatch) {
          return false;
        }
        if (defaultExcludes) {
          return !isDefaultExcluded(path);
        }
        return true;
      }
    };
    return filter;
  }

  ResourceFilter getCustomFilter(final String includeList[],
      final String excludeList[], final String skipList[],
      final boolean defaultExcludes, final boolean caseSensitive,
      final FilterFileType filterFileType) {
    if (includeList.length == 0 && excludeList.length == 0
        && skipList.length == 0 && caseSensitive) {
      // optimize for the common case.
      return getMatchingDefaultFilter(defaultExcludes, filterFileType);
    }

    // don't create a catchAll in default cases
    ResourceFilter catchAll = new ResourceFilter() {
      ZipScanner scanner = getScanner(includeList, excludeList, skipList,
          defaultExcludes, caseSensitive);

      @Override
      public boolean allows(String path) {
        return filterFileType.matches(path) && scanner.match(path);
      }
    };

    // for now, don't handle case sensitivity
    if (!caseSensitive) {
      return catchAll;
    }
    return customFilterWithCatchAll(includeList, excludeList, skipList,
        defaultExcludes, catchAll, filterFileType);
  }

  ResourceFilter getExcludesFilterPart(final String list[]) {
    return getFilterPart(list, false);
  }

  ResourceFilter getIncludesFilterPart(final String list[]) {
    return getFilterPart(list, true);
  }

  /**
   * @param list patterns to add to the filter.
   * @param isInclude Only used if the array is empty. If <code>true</code>
   *          treat this as an include. Otherwise, assume this is an excludes
   *          filter and exclude all files.
   * @return
   */
  private ResourceFilter getFilterPart(final String list[],
      final boolean isInclude) {
    if (list.length == 0) {
      return isInclude ? defaultAntIncludes : rejectAll;
    }

    String patternStrings[] = new String[list.length];
    int count = 0;
    for (String antPatternString : list) {
      String patternString = getPatternFromAntPattern(antPatternString);
      if (patternString == null) {
        return null;
      }
      patternStrings[count++] = patternString;
    }

    final Pattern pattern = getPatternFromStrings(patternStrings);
    return new ResourceFilter() {
      @Override
      public boolean allows(String path) {
        return pattern.matcher(path).matches();
      }
    };
  }

  /**
   * Obtain the appropriate resourceFilter based on defaultExcludes and isJava
   * values. Assumptions: caseSensitive = true,and the includesList and
   * excludesList are empty
   */
  private ResourceFilter getMatchingDefaultFilter(boolean defaultExcludes,
      FilterFileType filterFileType) {
    if (defaultExcludes) {
      return filterFileType.getDefaultFilter();
    }
    return filterFileType.getFileTypeFilter();
  }
}
