// Copyright (C) 2011 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.rules;

import static com.google.gerrit.common.data.Permission.LABEL;
import static com.google.gerrit.server.project.Util.allow;
import static com.google.gerrit.server.project.Util.category;
import static com.google.gerrit.server.project.Util.value;
import static org.easymock.EasyMock.expect;

import com.google.gerrit.common.data.LabelType;
import com.google.gerrit.common.data.LabelTypes;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.Util;
import com.google.gerrit.testutil.InMemoryRepositoryManager;
import com.google.inject.AbstractModule;

import com.googlecode.prolog_cafe.exceptions.CompileException;
import com.googlecode.prolog_cafe.exceptions.ReductionLimitException;
import com.googlecode.prolog_cafe.lang.JavaObjectTerm;
import com.googlecode.prolog_cafe.lang.Prolog;
import com.googlecode.prolog_cafe.lang.StructureTerm;
import com.googlecode.prolog_cafe.lang.SymbolTerm;

import org.easymock.EasyMock;
import org.eclipse.jgit.lib.Config;
import org.junit.Before;
import org.junit.Test;

import java.io.PushbackReader;
import java.io.StringReader;
import java.util.Arrays;

public class GerritCommonTest extends PrologTestCase {
  private final LabelType V = category("Verified",
      value(1, "Verified"),
      value(0, "No score"),
      value(-1, "Fails"));
  private final LabelType Q = category("Qualified",
      value(1, "Qualified"),
      value(0, "No score"),
      value(-1, "Fails"));

  private final Project.NameKey localKey = new Project.NameKey("local");
  private ProjectConfig local;
  private Util util;

  @Before
  public void setUp() throws Exception {
    util = new Util();
    load("gerrit", "gerrit_common_test.pl", new AbstractModule() {
      @Override
      protected void configure() {
        Config cfg = new Config();
        cfg.setInt("rules", null, "reductionLimit", 1300);
        cfg.setInt("rules", null, "compileReductionLimit", (int) 1e6);
        bind(PrologEnvironment.Args.class).toInstance(
            new PrologEnvironment.Args(
                null,
                null,
                null,
                null,
                null,
                null,
                cfg));
      }
    });

    local = new ProjectConfig(localKey);
    local.load(InMemoryRepositoryManager.newRepository(localKey));
    Q.setRefPatterns(Arrays.asList("refs/heads/develop"));

    local.getLabelSections().put(V.getName(), V);
    local.getLabelSections().put(Q.getName(), Q);
    util.add(local);
    allow(local, LABEL + V.getName(), -1, +1, SystemGroupBackend.REGISTERED_USERS, "refs/heads/*");
    allow(local, LABEL + Q.getName(), -1, +1, SystemGroupBackend.REGISTERED_USERS, "refs/heads/master");
  }

  @Override
  protected void setUpEnvironment(PrologEnvironment env) {
    LabelTypes labelTypes =
        new LabelTypes(Arrays.asList(Util.codeReview(), Util.verified()));
    ChangeControl ctl = EasyMock.createMock(ChangeControl.class);
    expect(ctl.getLabelTypes()).andStubReturn(labelTypes);
    EasyMock.replay(ctl);
    env.set(StoredValues.CHANGE_CONTROL, ctl);
  }

  @Test
  public void testGerritCommon() {
    runPrologBasedTests();
  }

  @Test
  public void testReductionLimit() throws CompileException {
    PrologEnvironment env = envFactory.create(machine);
    setUpEnvironment(env);

    String script = "loopy :- b(5).\n"
        + "b(N) :- N > 0, !, S = N - 1, b(S).\n"
        + "b(_) :- true.\n";

    SymbolTerm nameTerm = SymbolTerm.create("testReductionLimit");
    JavaObjectTerm inTerm = new JavaObjectTerm(
        new PushbackReader(new StringReader(script), Prolog.PUSHBACK_SIZE));
    if (!env.execute(Prolog.BUILTIN, "consult_stream", nameTerm, inTerm)) {
      throw new CompileException("Cannot consult " + nameTerm);
    }

    exception.expect(ReductionLimitException.class);
    exception.expectMessage("exceeded reduction limit of 1300");
    env.once(Prolog.BUILTIN, "call", new StructureTerm(":",
        SymbolTerm.create("user"), SymbolTerm.create("loopy")));
  }
}

@@ -654,535 +654,86 @@
 tic 
-com.google.gerrit.common.data.Permission.LABEL;%0Aimport static com.google.gerrit.server.project.Util.allow;%0Aimport static com.google.gerrit.server.project.Util.category;%0Aimport static com.google.gerrit.server.project.Util.value;%0Aimport static org.easymock.EasyMock.expect;%0A%0Aimport com.google.gerrit.common.data.LabelType;%0Aimport com.google.gerrit.common.data.LabelTypes;%0Aimport com.google.gerrit.reviewdb.client.Project;%0Aimport com.google.gerrit.server.git.ProjectConfig;%0Aimport com.google.gerrit.server.group.SystemGroupBackend
+org.easymock.EasyMock.expect;%0A%0Aimport com.google.gerrit.common.data.LabelTypes
 ;%0Aim
@@ -835,69 +835,8 @@
 il;%0A
-import com.google.gerrit.testutil.InMemoryRepositoryManager;%0A
 impo
@@ -1474,405 +1474,8 @@
 e %7B%0A
-  private final LabelType V = category(%22Verified%22,%0A      value(1, %22Verified%22),%0A      value(0, %22No score%22),%0A      value(-1, %22Fails%22));%0A  private final LabelType Q = category(%22Qualified%22,%0A      value(1, %22Qualified%22),%0A      value(0, %22No score%22),%0A      value(-1, %22Fails%22));%0A%0A  private final Project.NameKey localKey = new Project.NameKey(%22local%22);%0A  private ProjectConfig local;%0A  private Util util;%0A%0A
   @B
@@ -1525,31 +1525,8 @@
 n %7B%0A
-    util = new Util();%0A
     
@@ -2073,503 +2073,8 @@
  %7D);
-%0A%0A    local = new ProjectConfig(localKey);%0A    local.load(InMemoryRepositoryManager.newRepository(localKey));%0A    Q.setRefPatterns(Arrays.asList(%22refs/heads/develop%22));%0A%0A    local.getLabelSections().put(V.getName(), V);%0A    local.getLabelSections().put(Q.getName(), Q);%0A    util.add(local);%0A    allow(local, LABEL + V.getName(), -1, +1, SystemGroupBackend.REGISTERED_USERS, %22refs/heads/*%22);%0A    allow(local, LABEL + Q.getName(), -1, +1, SystemGroupBackend.REGISTERED_USERS, %22refs/heads/master%22);
 %0A  %7D

Remove unused code from GerritCommonTest