// 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.googlecode.prolog_cafe.lang.PrologMachineCopy.save;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.inject.Inject;
import com.google.inject.Singleton;

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.SymbolTerm;

import org.eclipse.jgit.errors.LargeObjectException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.util.RawParseUtils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PushbackReader;
import java.io.Reader;
import java.io.StringReader;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Manages a cache of compiled Prolog rules.
 * <p>
 * Rules are loaded from the {@code site_path/cache/rules/rules-SHA1.jar}, where
 * {@code SHA1} is the SHA1 of the Prolog {@code rules.pl} in a project's
 * {@link RefNames#REFS_CONFIG} branch.
 */
@Singleton
public class RulesCache {
  /** Maximum size of a dynamic Prolog script, in bytes. */
  private static final int SRC_LIMIT = 128 * 1024;

  /** Default size of the internal Prolog database within each interpreter. */
  private static final int DB_MAX = 256;

  private static final List<String> PACKAGE_LIST = ImmutableList.of(
      Prolog.BUILTIN, "gerrit");

  private final Map<ObjectId, MachineRef> machineCache =
      new HashMap<ObjectId, MachineRef>();

  private final ReferenceQueue<PrologMachineCopy> dead =
      new ReferenceQueue<PrologMachineCopy>();

  private static final class MachineRef extends WeakReference<PrologMachineCopy> {
    final ObjectId key;

    MachineRef(ObjectId key, PrologMachineCopy pcm,
        ReferenceQueue<PrologMachineCopy> queue) {
      super(pcm, queue);
      this.key = key;
    }
  }

  private final boolean enableProjectRules;
  private final File cacheDir;
  private final File rulesDir;
  private final GitRepositoryManager gitMgr;
  private final DynamicSet<PredicateProvider> predicateProviders;
  private final ClassLoader systemLoader;
  private final PrologMachineCopy defaultMachine;

  @Inject
  protected RulesCache(@GerritServerConfig Config config, SitePaths site,
      GitRepositoryManager gm, DynamicSet<PredicateProvider> predicateProviders) {
    enableProjectRules = config.getBoolean("rules", null, "enable", true);
    cacheDir = site.resolve(config.getString("cache", null, "directory"));
    rulesDir = cacheDir != null ? new File(cacheDir, "rules") : null;
    gitMgr = gm;
    this.predicateProviders = predicateProviders;

    systemLoader = getClass().getClassLoader();
    defaultMachine = save(newEmptyMachine(systemLoader));
  }

  public boolean isProjectRulesEnabled() {
    return enableProjectRules;
  }

  /**
   * Locate a cached Prolog machine state, or create one if not available.
   *
   * @return a Prolog machine, after loading the specified rules.
   * @throws CompileException the machine cannot be created.
   */
  public synchronized PrologMachineCopy loadMachine(
      Project.NameKey project,
      ObjectId rulesId)
      throws CompileException {
    if (!enableProjectRules || project == null || rulesId == null) {
      return defaultMachine;
    }

    Reference<? extends PrologMachineCopy> ref = machineCache.get(rulesId);
    if (ref != null) {
      PrologMachineCopy pmc = ref.get();
      if (pmc != null) {
        return pmc;
      }

      machineCache.remove(rulesId);
      ref.enqueue();
    }

    gc();

    PrologMachineCopy pcm = createMachine(project, rulesId);
    MachineRef newRef = new MachineRef(rulesId, pcm, dead);
    machineCache.put(rulesId, newRef);
    return pcm;
  }

  public PrologMachineCopy loadMachine(String name, InputStream in)
      throws CompileException {
    PrologMachineCopy pmc = consultRules(name, new InputStreamReader(in));
    if (pmc == null) {
      throw new CompileException("Cannot consult rules from the stream " + name);
    }
    return pmc;
  }

  private void gc() {
    Reference<?> ref;
    while ((ref = dead.poll()) != null) {
      ObjectId key = ((MachineRef) ref).key;
      if (machineCache.get(key) == ref) {
        machineCache.remove(key);
      }
    }
  }

  private PrologMachineCopy createMachine(Project.NameKey project,
      ObjectId rulesId) throws CompileException {
    // If the rules are available as a complied JAR on local disk, prefer
    // that over dynamic consult as the bytecode will be faster.
    //
    if (rulesDir != null) {
      File jarFile = new File(rulesDir, "rules-" + rulesId.getName() + ".jar");
      if (jarFile.isFile()) {
        URL[] cp = new URL[] {toURL(jarFile)};
        return save(newEmptyMachine(new URLClassLoader(cp, systemLoader)));
      }
    }

    // Dynamically consult the rules into the machine's internal database.
    //
    String rules = read(project, rulesId);
    PrologMachineCopy pmc = consultRules("rules.pl", new StringReader(rules));
    if (pmc == null) {
      throw new CompileException("Cannot consult rules of " + project);
    }
    return pmc;
  }

  private PrologMachineCopy consultRules(String name, Reader rules)
      throws CompileException {
    BufferingPrologControl ctl = newEmptyMachine(systemLoader);
    PushbackReader in = new PushbackReader(rules, Prolog.PUSHBACK_SIZE);
    try {
      if (!ctl.execute(Prolog.BUILTIN, "consult_stream",
          SymbolTerm.intern(name), new JavaObjectTerm(in))) {
        return null;
      }
    } catch (RuntimeException e) {
      throw new CompileException("Error while consulting rules from " + name, e);
    }
    return save(ctl);
  }

  private String read(Project.NameKey project, ObjectId rulesId)
      throws CompileException {
    Repository git;
    try {
      git = gitMgr.openRepository(project);
    } catch (RepositoryNotFoundException e) {
      throw new CompileException("Cannot open repository " + project, e);
    } catch (IOException e) {
      throw new CompileException("Cannot open repository " + project, e);
    }
    try {
      ObjectLoader ldr = git.open(rulesId, Constants.OBJ_BLOB);
      byte[] raw = ldr.getCachedBytes(SRC_LIMIT);
      return RawParseUtils.decode(raw);
    } catch (LargeObjectException e) {
      throw new CompileException("rules of " + project + " are too large", e);
    } catch (RuntimeException e) {
      throw new CompileException("Cannot load rules of " + project, e);
    } catch (IOException e) {
      throw new CompileException("Cannot load rules of " + project, e);
    } finally {
      git.close();
    }
  }

  private BufferingPrologControl newEmptyMachine(ClassLoader cl) {
    BufferingPrologControl ctl = new BufferingPrologControl();
    ctl.setMaxArity(PrologEnvironment.MAX_ARITY);
    ctl.setMaxDatabaseSize(DB_MAX);
    ctl.setPrologClassLoader(new PrologClassLoader(new PredicateClassLoader(
        predicateProviders, cl)));
    ctl.setEnabled(EnumSet.allOf(Prolog.Feature.class), false);

    List<String> packages = Lists.newArrayList();
    packages.addAll(PACKAGE_LIST);
    for (PredicateProvider predicateProvider : predicateProviders) {
      packages.addAll(predicateProvider.getPackages());
    }

    // Bootstrap the interpreter and ensure there is clean state.
    ctl.initialize(packages.toArray(new String[packages.size()]));
    return ctl;
  }

  private static URL toURL(File jarFile) throws CompileException {
    try {
      return jarFile.toURI().toURL();
    } catch (MalformedURLException e) {
      throw new CompileException("Cannot create URL for " + jarFile, e);
    }
  }
}
