// Copyright (C) 2014 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.util;

import static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.primitives.Chars;

import dk.brics.automaton.Automaton;
import dk.brics.automaton.RegExp;
import dk.brics.automaton.RunAutomaton;

import java.util.Collections;
import java.util.List;

/** Helper to search sorted lists for elements matching a regex. */
public abstract class RegexListSearcher<T> implements Function<T, String> {
  public static RegexListSearcher<String> ofStrings(String re) {
    return new RegexListSearcher<String>(re) {
      @Override
      public String apply(String in) {
        return in;
      }
    };
  }

  private final RunAutomaton pattern;

  private final String prefixBegin;
  private final String prefixEnd;
  private final int prefixLen;
  private final boolean prefixOnly;

  public RegexListSearcher(String re) {
    if (re.startsWith("^")) {
      re = re.substring(1);
    }

    if (re.endsWith("$") && !re.endsWith("\\$")) {
      re = re.substring(0, re.length() - 1);
    }

    Automaton automaton = new RegExp(re).toAutomaton();
    prefixBegin = automaton.getCommonPrefix();
    prefixLen = prefixBegin.length();

    if (0 < prefixLen) {
      char max = Chars.checkedCast(prefixBegin.charAt(prefixLen - 1) + 1);
      prefixEnd = prefixBegin.substring(0, prefixLen - 1) + max;
      prefixOnly = re.equals(prefixBegin + ".*");
    } else {
      prefixEnd = "";
      prefixOnly = false;
    }

    pattern = prefixOnly ? null : new RunAutomaton(automaton);
  }

  public Iterable<T> search(List<T> list) {
    checkNotNull(list);
    int begin, end;

    if (0 < prefixLen) {
      // Assumes many consecutive elements may have the same prefix, so the cost
      // of two binary searches is less than iterating to find the endpoints.
      begin = find(list, prefixBegin);
      end = find(list, prefixEnd);
    } else {
      begin = 0;
      end = list.size();
    }

    if (prefixOnly) {
      return begin < end ? list.subList(begin, end) : ImmutableList.<T> of();
    }

    return Iterables.filter(
        list.subList(begin, end),
        new Predicate<T>() {
          @Override
          public boolean apply(T in) {
            return pattern.run(RegexListSearcher.this.apply(in));
          }
        });
  }

  public boolean hasMatch(List<T> list) {
    return !Iterables.isEmpty(search(list));
  }

  private int find(List<T> list, String p) {
    int r = Collections.binarySearch(Lists.transform(list, this), p);
    return r < 0 ? -(r + 1) : r;
  }
}
