// 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 com.google.gerrit.server.util.TimeUtil;
import com.google.inject.Guice;
import com.google.inject.Module;

import com.googlecode.prolog_cafe.compiler.CompileException;
import com.googlecode.prolog_cafe.lang.BufferingPrologControl;
import com.googlecode.prolog_cafe.lang.JavaObjectTerm;
import com.googlecode.prolog_cafe.lang.Prolog;
import com.googlecode.prolog_cafe.lang.PrologClassLoader;
import com.googlecode.prolog_cafe.lang.PrologMachineCopy;
import com.googlecode.prolog_cafe.lang.StructureTerm;
import com.googlecode.prolog_cafe.lang.SymbolTerm;
import com.googlecode.prolog_cafe.lang.Term;
import com.googlecode.prolog_cafe.lang.VariableTerm;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PushbackReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;


/** Base class for any tests written in Prolog. */
public abstract class PrologTestCase {
  private static final SymbolTerm test_1 = SymbolTerm.intern("test", 1);

  private String pkg;
  private boolean hasSetup;
  private boolean hasTeardown;
  private List<Term> tests;
  private PrologMachineCopy machine;
  private PrologEnvironment.Factory envFactory;

  protected void load(String pkg, String prologResource, Module... modules)
      throws CompileException, IOException {
    ArrayList<Module> moduleList = new ArrayList<>();
    moduleList.add(new PrologModule.EnvironmentModule());
    moduleList.addAll(Arrays.asList(modules));

    envFactory = Guice.createInjector(moduleList)
        .getInstance(PrologEnvironment.Factory.class);
    PrologEnvironment env = envFactory.create(newMachine());
    consult(env, getClass(), prologResource);

    this.pkg = pkg;
    hasSetup = has(env, "setup");
    hasTeardown = has(env, "teardown");

    StructureTerm head = new StructureTerm(":",
        SymbolTerm.intern(pkg),
        new StructureTerm(test_1, new VariableTerm()));

    tests = new ArrayList<>();
    for (Term[] pair : env.all(Prolog.BUILTIN, "clause", head, new VariableTerm())) {
      tests.add(pair[0]);
    }
    assertTrue("has tests", tests.size() > 0);
    machine = PrologMachineCopy.save(env);
  }

  protected void setUpEnvironment(PrologEnvironment env) {
  }

  private PrologMachineCopy newMachine() {
    BufferingPrologControl ctl = new BufferingPrologControl();
    ctl.setMaxDatabaseSize(16 * 1024);
    ctl.setPrologClassLoader(new PrologClassLoader(getClass().getClassLoader()));
    return PrologMachineCopy.save(ctl);
  }

  protected void consult(BufferingPrologControl env,
      Class<?> clazz,
      String prologResource) throws CompileException, IOException {
    InputStream in = clazz.getResourceAsStream(prologResource);
    if (in == null) {
      throw new FileNotFoundException(prologResource);
    }
    try {
      SymbolTerm pathTerm = SymbolTerm.create(prologResource);
      JavaObjectTerm inTerm =
          new JavaObjectTerm(new PushbackReader(new BufferedReader(
              new InputStreamReader(in, "UTF-8")), Prolog.PUSHBACK_SIZE));
      if (!env.execute(Prolog.BUILTIN, "consult_stream", pathTerm, inTerm)) {
        throw new CompileException("Cannot consult " + prologResource);
      }
    } finally {
      in.close();
    }
  }

  private boolean has(BufferingPrologControl env, String name) {
    StructureTerm head = SymbolTerm.create(pkg, name, 0);
    return env.execute(Prolog.BUILTIN, "clause", head, new VariableTerm());
  }

  public void runPrologBasedTests() {
    int errors = 0;
    long start = TimeUtil.nowMs();

    for (Term test : tests) {
      PrologEnvironment env = envFactory.create(machine);
      setUpEnvironment(env);
      env.setEnabled(Prolog.Feature.IO, true);

      System.out.format("Prolog %-60s ...", removePackage(test));
      System.out.flush();

      if (hasSetup) {
        call(env, "setup");
      }

      List<Term> all = env.all(Prolog.BUILTIN, "call", test);

      if (hasTeardown) {
        call(env, "teardown");
      }

      System.out.println(all.size() == 1 ? "OK" : "FAIL");

      if (all.size() > 0 && !test.equals(all.get(0))) {
        for (Term t : all) {
          Term head = ((StructureTerm) removePackage(t)).args()[0];
          Term[] args = ((StructureTerm) head).args();
          System.out.print("  Result: ");
          for (int i = 0; i < args.length; i++) {
            if (0 < i) {
              System.out.print(", ");
            }
            System.out.print(args[i]);
          }
          System.out.println();
        }
        System.out.println();
      }

      if (all.size() != 1) {
       errors++;
      }
    }

    long end = TimeUtil.nowMs();
    System.out.println("-------------------------------");
    System.out.format("Prolog tests: %d, Failures: %d, Time elapsed %.3f sec",
        tests.size(), errors, (end - start) / 1000.0);
    System.out.println();

    assertEquals("No Errors", 0, errors);
  }

  private void call(BufferingPrologControl env, String name) {
    StructureTerm head = SymbolTerm.create(pkg, name, 0);
    if (!env.execute(Prolog.BUILTIN, "call", head)) {
      fail("Cannot invoke " + pkg + ":" + name);
    }
  }

  private Term removePackage(Term test) {
    Term name = test;
    if (name.isStructure() && ":".equals(((StructureTerm) name).name())) {
      name = ((StructureTerm) name).args()[1];
    }
    return name;
  }
}
