// Copyright (C) 2013 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.index;

import static com.google.gerrit.reviewdb.client.Change.Status.ABANDONED;
import static com.google.gerrit.reviewdb.client.Change.Status.DRAFT;
import static com.google.gerrit.reviewdb.client.Change.Status.MERGED;
import static com.google.gerrit.reviewdb.client.Change.Status.NEW;
import static com.google.gerrit.reviewdb.client.Change.Status.SUBMITTED;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;

import com.google.common.collect.ImmutableList;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.server.query.AndPredicate;
import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.server.query.QueryParseException;
import com.google.gerrit.server.query.change.AndSource;
import com.google.gerrit.server.query.change.BasicChangeRewrites;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.ChangeQueryBuilder;
import com.google.gerrit.server.query.change.OrSource;

import org.junit.Before;
import org.junit.Test;

import java.util.Arrays;
import java.util.EnumSet;
import java.util.Set;

public class IndexRewriteTest {
  private FakeIndex index;
  private IndexCollection indexes;
  private ChangeQueryBuilder queryBuilder;
  private IndexRewriteImpl rewrite;

  @Before
  public void setUp() throws Exception {
    index = new FakeIndex(FakeIndex.V2);
    indexes = new IndexCollection();
    indexes.setSearchIndex(index);
    queryBuilder = new FakeQueryBuilder(indexes);
    rewrite = new IndexRewriteImpl(
        indexes,
        new BasicChangeRewrites(null));
  }

  @Test
  public void testIndexPredicate() throws Exception {
    Predicate<ChangeData> in = parse("file:a");
    assertEquals(query(in), rewrite(in));
  }

  @Test
  public void testNonIndexPredicate() throws Exception {
    Predicate<ChangeData> in = parse("foo:a");
    assertSame(in, rewrite(in));
  }

  @Test
  public void testIndexPredicates() throws Exception {
    Predicate<ChangeData> in = parse("file:a file:b");
    assertEquals(query(in), rewrite(in));
  }

  @Test
  public void testNonIndexPredicates() throws Exception {
    Predicate<ChangeData> in = parse("foo:a OR foo:b");
    assertEquals(in, rewrite(in));
  }

  @Test
  public void testOneIndexPredicate() throws Exception {
    Predicate<ChangeData> in = parse("foo:a file:b");
    Predicate<ChangeData> out = rewrite(in);
    assertSame(AndSource.class, out.getClass());
    assertEquals(
        ImmutableList.of(query(in.getChild(1)), in.getChild(0)),
        out.getChildren());
  }

  @Test
  public void testThreeLevelTreeWithAllIndexPredicates() throws Exception {
    Predicate<ChangeData> in =
        parse("-status:abandoned (status:open OR status:merged)");
    assertEquals(
        query(parse("status:new OR status:submitted OR status:draft OR status:merged")),
        rewrite.rewrite(in, 0));
  }

  @Test
  public void testThreeLevelTreeWithSomeIndexPredicates() throws Exception {
    Predicate<ChangeData> in = parse("-foo:a (file:b OR file:c)");
    Predicate<ChangeData> out = rewrite(in);
    assertEquals(AndSource.class, out.getClass());
    assertEquals(
        ImmutableList.of(query(in.getChild(1)), in.getChild(0)),
        out.getChildren());
  }

  @Test
  public void testMultipleIndexPredicates() throws Exception {
    Predicate<ChangeData> in =
        parse("file:a OR foo:b OR file:c OR foo:d");
    Predicate<ChangeData> out = rewrite(in);
    assertSame(OrSource.class, out.getClass());
    assertEquals(ImmutableList.of(
          query(Predicate.or(in.getChild(0), in.getChild(2))),
          in.getChild(1), in.getChild(3)),
        out.getChildren());
  }

  @Test
  public void testIndexAndNonIndexPredicates() throws Exception {
    Predicate<ChangeData> in = parse("status:new bar:p file:a");
    Predicate<ChangeData> out = rewrite(in);
    assertSame(AndSource.class, out.getClass());
    assertEquals(ImmutableList.of(
          query(Predicate.and(in.getChild(0), in.getChild(2))),
          in.getChild(1)),
        out.getChildren());
  }

  @Test
  public void testDuplicateCompoundNonIndexOnlyPredicates() throws Exception {
    Predicate<ChangeData> in =
        parse("(status:new OR status:draft) bar:p file:a");
    Predicate<ChangeData> out = rewrite(in);
    assertSame(AndSource.class, out.getClass());
    assertEquals(ImmutableList.of(
          query(Predicate.and(in.getChild(0), in.getChild(2))),
          in.getChild(1)),
        out.getChildren());
  }

  @Test
  public void testDuplicateCompoundIndexOnlyPredicates() throws Exception {
    Predicate<ChangeData> in =
        parse("(status:new OR file:a) bar:p file:b");
    Predicate<ChangeData> out = rewrite(in);
    assertSame(AndSource.class, out.getClass());
    assertEquals(ImmutableList.of(
          query(Predicate.and(in.getChild(0), in.getChild(2))),
          in.getChild(1)),
        out.getChildren());
  }

  @Test
  public void testLimit() throws Exception {
    Predicate<ChangeData> in = parse("file:a limit:3");
    Predicate<ChangeData> out = rewrite(in);
    assertSame(AndSource.class, out.getClass());
    assertEquals(ImmutableList.of(
          query(in.getChild(0), 3),
          in.getChild(1)),
        out.getChildren());
  }

  @Test
  public void testStartIncreasesLimit() throws Exception {
    Predicate<ChangeData> f = parse("file:a");
    Predicate<ChangeData> l = parse("limit:3");
    Predicate<ChangeData> in = and(f, l);
    assertEquals(and(query(f, 3), l), rewrite.rewrite(in, 0));
    assertEquals(and(query(f, 4), l), rewrite.rewrite(in, 1));
    assertEquals(and(query(f, 5), l), rewrite.rewrite(in, 2));
  }

  @Test
  public void testStartDoesNotExceedMaxLimit() throws Exception {
    Predicate<ChangeData> in = parse("file:a");
    assertEquals(query(in), rewrite.rewrite(in, 0));
    assertEquals(query(in), rewrite.rewrite(in, 1));
  }

  @Test
  public void testGetPossibleStatus() throws Exception {
    assertEquals(EnumSet.allOf(Change.Status.class), status("file:a"));
    assertEquals(EnumSet.of(NEW), status("is:new"));
    assertEquals(EnumSet.of(SUBMITTED, DRAFT, MERGED, ABANDONED),
        status("-is:new"));
    assertEquals(EnumSet.of(NEW, MERGED), status("is:new OR is:merged"));

    EnumSet<Change.Status> none = EnumSet.noneOf(Change.Status.class);
    assertEquals(none, status("is:new is:merged"));
    assertEquals(none, status("(is:new is:draft) (is:merged is:submitted)"));
    assertEquals(none, status("(is:new is:draft) (is:merged is:submitted)"));

    assertEquals(EnumSet.of(MERGED, SUBMITTED),
        status("(is:new is:draft) OR (is:merged OR is:submitted)"));
  }

  @Test
  public void testUnsupportedIndexOperator() throws Exception {
    Predicate<ChangeData> in = parse("status:merged file:a");
    assertEquals(query(in), rewrite(in));

    indexes.setSearchIndex(new FakeIndex(FakeIndex.V1));
    Predicate<ChangeData> out = rewrite(in);
    assertTrue(out instanceof AndPredicate);
    assertEquals(ImmutableList.of(
          query(in.getChild(0)),
          in.getChild(1)),
        out.getChildren());
  }

  private Predicate<ChangeData> parse(String query) throws QueryParseException {
    return queryBuilder.parse(query);
  }

  @SafeVarargs
  private static AndSource and(Predicate<ChangeData>... preds) {
    return new AndSource(Arrays.asList(preds));
  }

  private Predicate<ChangeData> rewrite(Predicate<ChangeData> in)
      throws QueryParseException {
    return rewrite.rewrite(in, 0);
  }

  private IndexedChangeQuery query(Predicate<ChangeData> p)
      throws QueryParseException {
    return query(p, IndexRewriteImpl.MAX_LIMIT);
  }

  private IndexedChangeQuery query(Predicate<ChangeData> p, int limit)
      throws QueryParseException {
    return new IndexedChangeQuery(index, p, limit);
  }

  private Set<Change.Status> status(String query) throws QueryParseException {
    return IndexRewriteImpl.getPossibleStatus(parse(query));
  }
}
