// 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 static com.googlesource.gerrit.owners.common.StreamUtils.iteratorStream;

import com.google.gerrit.entities.Account;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.rules.PrologEnvironment;
import com.google.gerrit.server.rules.StoredValues;
import com.googlecode.prolog_cafe.exceptions.PInstantiationException;
import com.googlecode.prolog_cafe.exceptions.PrologException;
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.SymbolTerm;
import com.googlecode.prolog_cafe.lang.Term;
import com.googlecode.prolog_cafe.lang.VariableTerm;
import com.googlesource.gerrit.owners.OwnersStoredValues;
import com.googlesource.gerrit.owners.common.PathOwners;
import java.io.File;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Get the list of users owning this file Actually a variation of PRED_current_user/2 in gerrit main
 * module, sharing its cache.. This is really needed to avoid prolog consuming rules and RAM space
 *
 * <pre>
 *   gerrit_owners:file_owners(+FilePath, -UserListFormatted).
 * </pre>
 */
class PRED_file_owners_2 extends Predicate.P2 {

  PRED_file_owners_2(Term a1, Term a2, Operation n) {
    arg1 = a1;
    arg2 = a2;
    cont = n;
  }

  @Override
  public Operation exec(Prolog engine) throws PrologException {
    engine.setB0();
    Term a1 = arg1.dereference();
    Term a2 = arg2.dereference();
    if (a1 instanceof VariableTerm) {
      throw new PInstantiationException(this, 1);
    }
    if (!a2.unify(createFormattedList(engine, a1), engine.trail)) {
      return engine.fail();
    }
    return cont;
  }

  public String getFullNameFromId(Prolog engine, Account.Id accountId) {
    Map<Account.Id, IdentifiedUser> cache = StoredValues.USERS.get(engine);
    IdentifiedUser user = cache.get(accountId);
    if (user == null) {
      IdentifiedUser.GenericFactory userFactory = userFactory(engine);
      IdentifiedUser who = userFactory.create(accountId);
      cache.put(accountId, who);
      user = who;
    }
    Account account = user.asIdentifiedUser().state().account();
    String userName = account.fullName();
    return sanitizeAsSubmitLabel(userName);
  }

  public Term createFormattedList(Prolog engine, Term key) {
    String path = key.toString();
    PathOwners owners = OwnersStoredValues.PATH_OWNERS.get(engine);
    Set<String> ownersNames =
        owners.expandGroups()
            ? iteratorStream(owners.getFileOwners().get(path).iterator())
                .map(id -> getFullNameFromId(engine, id))
                .collect(Collectors.toSet())
            : iteratorStream((owners.getFileGroupOwners().get(path)).iterator())
                .collect(Collectors.toSet());
    String ownVerb = ownersNames.size() > 1 ? "-own-" : "-owns-";
    String userNames = ownersNames.stream().collect(Collectors.joining("-"));
    return SymbolTerm.create(userNames + ownVerb + sanitizeAsSubmitLabel(new File(path).getName()));
  }

  private String sanitizeAsSubmitLabel(String anyLabelPart) {
    return anyLabelPart.replaceAll("[\\s_\\.]+", "-");
  }

  private static IdentifiedUser.GenericFactory userFactory(Prolog engine) {
    return ((PrologEnvironment) engine.control).getArgs().getUserFactory();
  }
}
