// 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 gerrit;

import com.google.gerrit.reviewdb.client.Patch;
import com.google.gerrit.rules.StoredValues;
import com.google.gerrit.server.patch.PatchList;
import com.google.gerrit.server.patch.PatchListEntry;

import com.googlecode.prolog_cafe.lang.IllegalTypeException;
import com.googlecode.prolog_cafe.lang.JavaObjectTerm;
import com.googlecode.prolog_cafe.lang.Operation;
import com.googlecode.prolog_cafe.lang.PInstantiationException;
import com.googlecode.prolog_cafe.lang.Predicate;
import com.googlecode.prolog_cafe.lang.Prolog;
import com.googlecode.prolog_cafe.lang.PrologException;
import com.googlecode.prolog_cafe.lang.SymbolTerm;
import com.googlecode.prolog_cafe.lang.Term;

import java.util.Iterator;
import java.util.regex.Pattern;

/**
 * Given a regular expression, checks it against the file list in the most
 * recent patchset of a change. For all files that match the regex, returns the
 * (new) path of the file, the change type, and the old path of the file if
 * applicable (if the file was copied or renamed).
 *
 * <pre>
 *   'commit_delta'(+Regex, -ChangeType, -NewPath, -OldPath)
 * </pre>
 */
public class PRED_commit_delta_4 extends Predicate.P4 {
  private static final SymbolTerm add = SymbolTerm.intern("add");
  private static final SymbolTerm modify = SymbolTerm.intern("modify");
  private static final SymbolTerm delete = SymbolTerm.intern("delete");
  private static final SymbolTerm rename = SymbolTerm.intern("rename");
  private static final SymbolTerm copy = SymbolTerm.intern("copy");
  static final Operation commit_delta_check = new PRED_commit_delta_check();
  static final Operation commit_delta_next = new PRED_commit_delta_next();
  static final Operation commit_delta_empty = new PRED_commit_delta_empty();

  public PRED_commit_delta_4(Term a1, Term a2, Term a3, Term a4, Operation n) {
    arg1 = a1;
    arg2 = a2;
    arg3 = a3;
    arg4 = a4;
    cont = n;
  }

  @Override
  public Operation exec(Prolog engine) throws PrologException {
    engine.cont = cont;
    engine.setB0();

    Term a1 = arg1.dereference();
    if (a1.isVariable()) {
      throw new PInstantiationException(this, 1);
    }
    if (!a1.isSymbol()) {
      throw new IllegalTypeException(this, 1, "symbol", a1);
    }
    Pattern regex = Pattern.compile(a1.name());
    engine.areg1 = new JavaObjectTerm(regex);
    engine.areg2 = arg2;
    engine.areg3 = arg3;
    engine.areg4 = arg4;

    PatchList pl = StoredValues.PATCH_LIST.get(engine);
    Iterator<PatchListEntry> iter = pl.getPatches().iterator();

    engine.areg5 = new JavaObjectTerm(iter);

    return engine.jtry5(commit_delta_check, commit_delta_next);
  }

  private static final class PRED_commit_delta_check extends Operation {
    @Override
    public Operation exec(Prolog engine) {
      Term a1 = engine.areg1;
      Term a2 = engine.areg2;
      Term a3 = engine.areg3;
      Term a4 = engine.areg4;
      Term a5 = engine.areg5;

      Pattern regex = (Pattern)((JavaObjectTerm)a1).object();
      @SuppressWarnings("unchecked")
      Iterator<PatchListEntry> iter =
        (Iterator<PatchListEntry>)((JavaObjectTerm)a5).object();
      while (iter.hasNext()) {
        PatchListEntry patch = iter.next();
        String newName = patch.getNewName();
        String oldName = patch.getOldName();
        Patch.ChangeType changeType = patch.getChangeType();

        if (newName.equals("/COMMIT_MSG")) {
          continue;
        }

        if (regex.matcher(newName).find() ||
            (oldName != null && regex.matcher(oldName).find())) {
          SymbolTerm changeSym = getTypeSymbol(changeType);
          SymbolTerm newSym = SymbolTerm.create(newName);
          SymbolTerm oldSym = Prolog.Nil;
          if (oldName != null) {
            oldSym = SymbolTerm.create(oldName);
          }

          if (!a2.unify(changeSym, engine.trail)) {
            continue;
          }
          if (!a3.unify(newSym, engine.trail)) {
            continue;
          }
          if (!a4.unify(oldSym, engine.trail)) {
            continue;
          }
          return engine.cont;
        }
      }
      return engine.fail();
    }
  }

  private static final class PRED_commit_delta_next extends Operation {
    @Override
    public Operation exec(Prolog engine) {
      return engine.trust(commit_delta_empty);
    }
  }

  private static final class PRED_commit_delta_empty extends Operation {
    @Override
    public Operation exec(Prolog engine) {
      Term a5 = engine.areg5;

      @SuppressWarnings("unchecked")
      Iterator<PatchListEntry> iter =
        (Iterator<PatchListEntry>)((JavaObjectTerm)a5).object();
      if (!iter.hasNext()) {
        return engine.fail();
      }

      return engine.jtry5(commit_delta_check, commit_delta_next);
    }
  }

  private static SymbolTerm getTypeSymbol(Patch.ChangeType type) {
    switch (type) {
      case ADDED:
        return add;
      case MODIFIED:
        return modify;
      case DELETED:
        return delete;
      case RENAMED:
        return rename;
      case COPIED:
        return copy;
      case REWRITE:
        break;
    }
    throw new IllegalArgumentException("ChangeType not recognized");
  }
}