// Copyright (C) 2015 The Android Open Source Project
//
// 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.gerrit.server.project;

import com.google.common.base.Predicate;
import com.google.common.base.Strings;
import com.google.common.collect.FluentIterable;
import com.google.gerrit.extensions.api.projects.RefInfo;
import com.google.gerrit.extensions.restapi.BadRequestException;
import dk.brics.automaton.RegExp;
import dk.brics.automaton.RunAutomaton;
import java.util.List;
import java.util.Locale;

public class RefFilter<T extends RefInfo> {
  private final String prefix;
  private String matchSubstring;
  private String matchRegex;
  private int start;
  private int limit;

  public RefFilter(String prefix) {
    this.prefix = prefix;
  }

  public RefFilter<T> subString(String subString) {
    this.matchSubstring = subString;
    return this;
  }

  public RefFilter<T> regex(String regex) {
    this.matchRegex = regex;
    return this;
  }

  public RefFilter<T> start(int start) {
    this.start = start;
    return this;
  }

  public RefFilter<T> limit(int limit) {
    this.limit = limit;
    return this;
  }

  public List<T> filter(List<T> refs) throws BadRequestException {
    if (!Strings.isNullOrEmpty(matchSubstring) && !Strings.isNullOrEmpty(matchRegex)) {
      throw new BadRequestException("specify exactly one of m/r");
    }
    FluentIterable<T> results = FluentIterable.from(refs);
    if (!Strings.isNullOrEmpty(matchSubstring)) {
      results = results.filter(new SubstringPredicate(matchSubstring));
    } else if (!Strings.isNullOrEmpty(matchRegex)) {
      results = results.filter(new RegexPredicate(matchRegex));
    }
    if (start > 0) {
      results = results.skip(start);
    }
    if (limit > 0) {
      results = results.limit(limit);
    }
    return results.toList();
  }

  private class SubstringPredicate implements Predicate<T> {
    private final String substring;

    private SubstringPredicate(String substring) {
      this.substring = substring.toLowerCase(Locale.US);
    }

    @Override
    public boolean apply(T in) {
      String ref = in.ref;
      if (ref.startsWith(prefix)) {
        ref = ref.substring(prefix.length());
      }
      ref = ref.toLowerCase(Locale.US);
      return ref.contains(substring);
    }
  }

  private class RegexPredicate implements Predicate<T> {
    private final RunAutomaton a;

    private RegexPredicate(String regex) throws BadRequestException {
      if (regex.startsWith("^")) {
        regex = regex.substring(1);
        if (regex.endsWith("$") && !regex.endsWith("\\$")) {
          regex = regex.substring(0, regex.length() - 1);
        }
      }
      try {
        a = new RunAutomaton(new RegExp(regex).toAutomaton());
      } catch (IllegalArgumentException e) {
        throw new BadRequestException(e.getMessage());
      }
    }

    @Override
    public boolean apply(T in) {
      String ref = in.ref;
      if (ref.startsWith(prefix)) {
        ref = ref.substring(prefix.length());
      }
      return a.run(ref);
    }
  }
}
