/*
 * Copyright 2012-present Facebook, 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.facebook.buck.android;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;

/**
 * Filter for internal class names.
 *
 * <p>We use this to determine if a class must be placed in our primary dex.
 * It supports prefix, suffix, substring, and exact matches.
 */
public class ClassNameFilter {
  // We use naive algorithms for prefix, suffix, and substring, but these could easily be
  // optimzied using RE2 or some other more specialized search algorithms.
  private final ImmutableList<String> prefixes;
  private final ImmutableList<String> suffixes;
  private final ImmutableList<String> substrings;
  private final ImmutableSet<String> exactMatches;

  private ClassNameFilter(
      Iterable<String> prefixes,
      Iterable<String> suffixes,
      Iterable<String> substrings,
      Iterable<String> exactMatches) {
    this.prefixes = ImmutableList.copyOf(prefixes);
    this.suffixes = ImmutableList.copyOf(suffixes);
    this.substrings = ImmutableList.copyOf(substrings);
    this.exactMatches = ImmutableSet.copyOf(exactMatches);
  }

  /**
   * Convenience factory to produce a filter from a very simple pattern language.
   *
   * <p>patterns are substrings by default, but {@code ^} at the start or end of a pattern
   * anchors it to the start or end of the class name.
   *
   * @param patterns  Patterns to include in the filter.
   * @return  A new filter.
   */
  public static ClassNameFilter fromConfiguration(Iterable<String> patterns) {
    ImmutableList.Builder<String> prefixes = ImmutableList.builder();
    ImmutableList.Builder<String> suffixes = ImmutableList.builder();
    ImmutableList.Builder<String> substrings = ImmutableList.builder();
    ImmutableSet.Builder<String> exactMatches = ImmutableSet.builder();

    for (String pattern : patterns) {
      boolean isPrefix = pattern.charAt(0) == '^';
      boolean isSuffix = pattern.charAt(pattern.length() - 1) == '^';
      if (isPrefix && isSuffix) {
        exactMatches.add(pattern.substring(1, pattern.length() - 1));
      } else if (isPrefix) {
        prefixes.add(pattern.substring(1));
      } else if (isSuffix) {
        suffixes.add(pattern.substring(0, pattern.length() - 1));
      } else {
        substrings.add(pattern);
      }
    }

    return new ClassNameFilter(
        prefixes.build(),
        suffixes.build(),
        substrings.build(),
        exactMatches.build());
  }

  public boolean matches(String internalClassName) {
    if (exactMatches.contains(internalClassName)) {
      return true;
    }

    for (String prefix : prefixes) {
      if (internalClassName.startsWith(prefix)) {
        return true;
      }
    }

    for (String suffix : suffixes) {
      if (internalClassName.endsWith(suffix)) {
        return true;
      }
    }

    for (String substring : substrings) {
      if (internalClassName.contains(substring)) {
        return true;
      }
    }

    return false;
  }
}
