// Copyright (c) 2013 VMware, Inc. All Rights Reserved.
// Copyright (C) 2017 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_owners;

import com.google.gerrit.entities.Account;
import com.googlecode.prolog_cafe.exceptions.PrologException;
import com.googlecode.prolog_cafe.lang.IntegerTerm;
import com.googlecode.prolog_cafe.lang.JavaObjectTerm;
import com.googlecode.prolog_cafe.lang.Operation;
import com.googlecode.prolog_cafe.lang.Predicate;
import com.googlecode.prolog_cafe.lang.Prolog;
import com.googlecode.prolog_cafe.lang.StructureTerm;
import com.googlecode.prolog_cafe.lang.SymbolTerm;
import com.googlecode.prolog_cafe.lang.Term;
import com.googlesource.gerrit.owners.OwnersStoredValues;
import com.googlesource.gerrit.owners.common.PathOwners;
import java.util.Iterator;
import java.util.Map;

/** 'owner'(-Path, -User) */
public class PRED_matcher_owner_2 extends Predicate.P2 {

  private static final PRED_owner_check OWNER_CHECK = new PRED_owner_check();
  private static final PRED_owner_empty OWNER_EMPTY = new PRED_owner_empty();
  private static final PRED_owner_next OWNER_NEXT = new PRED_owner_next();

  public PRED_matcher_owner_2(Term a1, Term a2, Operation n) {
    this.arg1 = a1;
    this.arg2 = a2;
    this.cont = n;
  }

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

    PathOwners owners = OwnersStoredValues.PATH_OWNERS.get(engine);
    engine.r1 = arg1;
    engine.r2 = arg2;

    Term term = engine.r1.dereference();
    String path = term.toString();
    engine.r3 = new JavaObjectTerm(owners.getFileOwners().get(path).iterator());
    return engine.jtry3(OWNER_CHECK, OWNER_NEXT);
  }

  private static class PRED_owner_check extends Operation {

    @Override
    public Operation exec(Prolog engine) throws PrologException {
      Term a1 = engine.r1;
      Term a2 = engine.r2;
      Term a3 = engine.r3;

      Term term = engine.r1.dereference();
      String pathS = term.toString();

      @SuppressWarnings("unchecked")
      Iterator<Account.Id> iter = (Iterator<Account.Id>) ((JavaObjectTerm) a3).object();
      while (iter.hasNext()) {
        Account.Id entry = iter.next();

        SymbolTerm path = SymbolTerm.create(pathS);
        if (!a1.unify(path, engine.trail)) {
          continue;
        }

        StructureTerm user = new StructureTerm("user", new IntegerTerm(entry.get()));
        if (!a2.unify(user, engine.trail)) {
          continue;
        }

        return engine.cont;
      }
      return engine.fail();
    }
  }

  private static class PRED_owner_next extends Operation {

    @Override
    public Operation exec(Prolog engine) throws PrologException {
      return engine.trust(OWNER_EMPTY);
    }
  }

  private static class PRED_owner_empty extends Operation {

    @Override
    public Operation exec(Prolog engine) throws PrologException {
      Term a3 = engine.r3;

      @SuppressWarnings("unchecked")
      Iterator<Map.Entry<String, Account.Id>> iter =
          (Iterator<Map.Entry<String, Account.Id>>) ((JavaObjectTerm) a3).object();
      if (!iter.hasNext()) {
        return engine.fail();
      }

      return engine.jtry3(OWNER_CHECK, OWNER_NEXT);
    }
  }
}
