// 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 {
    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);
    }
  }
}
