// Copyright (C) 2009 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.server.project;

import com.google.gerrit.common.data.PermissionRange;
import com.google.gerrit.common.data.SubmitRecord;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.rules.PrologEnvironment;
import com.google.gerrit.rules.StoredValues;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.util.Providers;

import com.googlecode.prolog_cafe.compiler.CompileException;
import com.googlecode.prolog_cafe.lang.IntegerTerm;
import com.googlecode.prolog_cafe.lang.ListTerm;
import com.googlecode.prolog_cafe.lang.Prolog;
import com.googlecode.prolog_cafe.lang.PrologException;
import com.googlecode.prolog_cafe.lang.StructureTerm;
import com.googlecode.prolog_cafe.lang.Term;
import com.googlecode.prolog_cafe.lang.VariableTerm;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.Nullable;


/** Access control management for a user accessing a single change. */
public class ChangeControl {
  private static final Logger log = LoggerFactory
      .getLogger(ChangeControl.class);

  public static class GenericFactory {
    private final ProjectControl.GenericFactory projectControl;

    @Inject
    GenericFactory(ProjectControl.GenericFactory p) {
      projectControl = p;
    }

    public ChangeControl controlFor(Change change, CurrentUser user)
        throws NoSuchChangeException {
      final Project.NameKey projectKey = change.getProject();
      try {
        return projectControl.controlFor(projectKey, user).controlFor(change);
      } catch (NoSuchProjectException e) {
        throw new NoSuchChangeException(change.getId(), e);
      }
    }
  }

  public static class Factory {
    private final ProjectControl.Factory projectControl;
    private final Provider<ReviewDb> db;

    @Inject
    Factory(final ProjectControl.Factory p, final Provider<ReviewDb> d) {
      projectControl = p;
      db = d;
    }

    public ChangeControl controlFor(final Change.Id id)
        throws NoSuchChangeException {
      final Change change;
      try {
        change = db.get().changes().get(id);
        if (change == null) {
          throw new NoSuchChangeException(id);
        }
      } catch (OrmException e) {
        throw new NoSuchChangeException(id, e);
      }
      return controlFor(change);
    }

    public ChangeControl controlFor(final Change change)
        throws NoSuchChangeException {
      try {
        final Project.NameKey projectKey = change.getProject();
        return projectControl.validateFor(projectKey).controlFor(change);
      } catch (NoSuchProjectException e) {
        throw new NoSuchChangeException(change.getId(), e);
      }
    }

    public ChangeControl validateFor(final Change.Id id)
        throws NoSuchChangeException, OrmException {
      return validate(controlFor(id), db.get());
    }

    public ChangeControl validateFor(final Change change)
        throws NoSuchChangeException, OrmException {
      return validate(controlFor(change), db.get());
    }

    private static ChangeControl validate(final ChangeControl c, final ReviewDb db)
        throws NoSuchChangeException, OrmException{
      if (!c.isVisible(db)) {
        throw new NoSuchChangeException(c.getChange().getId());
      }
      return c;
    }
  }

  private final RefControl refControl;
  private final Change change;

  ChangeControl(final RefControl r, final Change c) {
    this.refControl = r;
    this.change = c;
  }

  public ChangeControl forUser(final CurrentUser who) {
    return new ChangeControl(getRefControl().forUser(who), getChange());
  }

  public RefControl getRefControl() {
    return refControl;
  }

  public CurrentUser getCurrentUser() {
    return getRefControl().getCurrentUser();
  }

  public ProjectControl getProjectControl() {
    return getRefControl().getProjectControl();
  }

  public Project getProject() {
    return getProjectControl().getProject();
  }

  public Change getChange() {
    return change;
  }

  /** Can this user see this change? */
  public boolean isVisible(ReviewDb db) throws OrmException {
    if (change.getStatus() == Change.Status.DRAFT && !isDraftVisible(db, null)) {
      return false;
    }
    return isRefVisible();
  }

  /** Can the user see this change? Does not account for draft status */
  public boolean isRefVisible() {
    return getRefControl().isVisible();
  }

  /** Can this user see the given patchset? */
  public boolean isPatchVisible(PatchSet ps, ReviewDb db) throws OrmException {
    if (ps.isDraft() && !isDraftVisible(db, null)) {
      return false;
    }
    return isVisible(db);
  }

  /** Can this user abandon this change? */
  public boolean canAbandon() {
    return isOwner() // owner (aka creator) of the change can abandon
        || getRefControl().isOwner() // branch owner can abandon
        || getProjectControl().isOwner() // project owner can abandon
        || getCurrentUser().getCapabilities().canAdministrateServer() // site administers are god
        || getRefControl().canAbandon() // user can abandon a specific ref
    ;
  }

  /** Can this user publish this draft change or any draft patch set of this change? */
  public boolean canPublish(final ReviewDb db) throws OrmException {
    return isOwner() && isVisible(db);
  }

  /** Can this user delete this draft change or any draft patch set of this change? */
  public boolean canDeleteDraft(final ReviewDb db) throws OrmException {
    return isOwner() && isVisible(db);
  }

  /** Can this user rebase this change? */
  public boolean canRebase() {
    return isOwner() || getRefControl().canSubmit()
        || getRefControl().canRebase();
  }

  /** Can this user restore this change? */
  public boolean canRestore() {
    return canAbandon() // Anyone who can abandon the change can restore it back
        && getRefControl().canUpload(); // as long as you can upload too
  }

  /** All value ranges of any allowed label permission. */
  public List<PermissionRange> getLabelRanges() {
    return getRefControl().getLabelRanges();
  }

  /** The range of permitted values associated with a label permission. */
  public PermissionRange getRange(String permission) {
    return getRefControl().getRange(permission);
  }

  /** Can this user add a patch set to this change? */
  public boolean canAddPatchSet() {
    return getRefControl().canUpload();
  }

  /** Is this user the owner of the change? */
  public boolean isOwner() {
    if (getCurrentUser() instanceof IdentifiedUser) {
      final IdentifiedUser i = (IdentifiedUser) getCurrentUser();
      return i.getAccountId().equals(change.getOwner());
    }
    return false;
  }

  /** Is this user a reviewer for the change? */
  public boolean isReviewer(ReviewDb db) throws OrmException {
    return isReviewer(db, null);
  }

  /** Is this user a reviewer for the change? */
  public boolean isReviewer(ReviewDb db, @Nullable ChangeData cd)
      throws OrmException {
    if (getCurrentUser() instanceof IdentifiedUser) {
      final IdentifiedUser user = (IdentifiedUser) getCurrentUser();
      Iterable<PatchSetApproval> results;
      if (cd != null) {
        results = cd.currentApprovals(Providers.of(db));
      } else {
        results = db.patchSetApprovals().byChange(change.getId());
      }
      for (PatchSetApproval approval : results) {
        if (user.getAccountId().equals(approval.getAccountId())) {
          return true;
        }
      }
    }
    return false;
  }

  /** @return true if the user is allowed to remove this reviewer. */
  public boolean canRemoveReviewer(PatchSetApproval approval) {
    if (getChange().getStatus().isOpen()) {
      // A user can always remove themselves.
      //
      if (getCurrentUser() instanceof IdentifiedUser) {
        final IdentifiedUser i = (IdentifiedUser) getCurrentUser();
        if (i.getAccountId().equals(approval.getAccountId())) {
          return true; // can remove self
        }
      }

      // The change owner may remove any zero or positive score.
      //
      if (isOwner() && 0 <= approval.getValue()) {
        return true;
      }

      // The branch owner, project owner, site admin can remove anyone.
      //
      if (getRefControl().isOwner() // branch owner
          || getProjectControl().isOwner() // project owner
          || getCurrentUser().getCapabilities().canAdministrateServer()) {
        return true;
      }
    }

    return false;
  }

  public List<SubmitRecord> getSubmitRecords(ReviewDb db, PatchSet patchSet) {
    return canSubmit(db, patchSet, null, false, true);
  }

  public List<SubmitRecord> canSubmit(ReviewDb db, PatchSet patchSet) {
    return canSubmit(db, patchSet, null, false, false);
  }

  public List<SubmitRecord> canSubmit(ReviewDb db, PatchSet patchSet,
      @Nullable ChangeData cd, boolean fastEvalLabels, boolean allowClosed) {
    if (!allowClosed && change.getStatus().isClosed()) {
      SubmitRecord rec = new SubmitRecord();
      rec.status = SubmitRecord.Status.CLOSED;
      return Collections.singletonList(rec);
    }

    if (!patchSet.getId().equals(change.currentPatchSetId())) {
      return ruleError("Patch set " + patchSet.getPatchSetId() + " is not current");
    }

    try {
      if (change.getStatus() == Change.Status.DRAFT) {
        if (!isDraftVisible(db, cd)) {
          return ruleError("Patch set " + patchSet.getPatchSetId() + " not found");
        } else {
          return ruleError("Cannot submit draft changes");
        }
      }
      if (patchSet.isDraft()) {
        if (!isDraftVisible(db, cd)) {
          return ruleError("Patch set " + patchSet.getPatchSetId() + " not found");
        } else {
          return ruleError("Cannot submit draft patch sets");
        }
      }
    } catch (OrmException err) {
      return logRuleError("Cannot read patch set " + patchSet.getId(), err);
    }

    List<Term> results = new ArrayList<Term>();
    Term submitRule;
    ProjectState projectState = getProjectControl().getProjectState();
    PrologEnvironment env;

    try {
      env = projectState.newPrologEnvironment();
    } catch (CompileException err) {
      return logRuleError("Cannot consult rules.pl for "
          + getProject().getName(), err);
    }

    try {
      env.set(StoredValues.REVIEW_DB, db);
      env.set(StoredValues.CHANGE, change);
      env.set(StoredValues.CHANGE_DATA, cd);
      env.set(StoredValues.PATCH_SET, patchSet);
      env.set(StoredValues.CHANGE_CONTROL, this);

      submitRule = env.once(
        "gerrit", "locate_submit_rule",
        new VariableTerm());
      if (submitRule == null) {
        return logRuleError("No user:submit_rule found for "
            + getProject().getName());
      }

      if (fastEvalLabels) {
        env.once("gerrit", "assume_range_from_label");
      }

      try {
        for (Term[] template : env.all(
            "gerrit", "can_submit",
            submitRule,
            new VariableTerm())) {
          results.add(template[1]);
        }
      } catch (PrologException err) {
        return logRuleError("Exception calling " + submitRule + " on change "
            + change.getId() + " of " + getProject().getName(), err);
      } catch (RuntimeException err) {
        return logRuleError("Exception calling " + submitRule + " on change "
            + change.getId() + " of " + getProject().getName(), err);
      }

      ProjectState parentState = projectState.getParentState();
      PrologEnvironment childEnv = env;
      Set<Project.NameKey> projectsSeen = new HashSet<Project.NameKey>();
      projectsSeen.add(getProject().getNameKey());

      while (parentState != null) {
        if (!projectsSeen.add(parentState.getProject().getNameKey())) {
          //parent has been seen before, stop walk up inheritance tree
          break;
        }
        PrologEnvironment parentEnv;
        try {
          parentEnv = parentState.newPrologEnvironment();
        } catch (CompileException err) {
          return logRuleError("Cannot consult rules.pl for "
              + parentState.getProject().getName(), err);
        }

        parentEnv.copyStoredValues(childEnv);
        Term filterRule =
            parentEnv.once("gerrit", "locate_submit_filter", new VariableTerm());
        if (filterRule != null) {
          try {
            if (fastEvalLabels) {
              env.once("gerrit", "assume_range_from_label");
            }

            Term resultsTerm = toListTerm(results);
            results.clear();
            Term[] template = parentEnv.once(
                "gerrit", "filter_submit_results",
                filterRule,
                resultsTerm,
                new VariableTerm());
            @SuppressWarnings("unchecked")
            final List<? extends Term> termList = ((ListTerm) template[2]).toJava();
            results.addAll(termList);
          } catch (PrologException err) {
            return logRuleError("Exception calling " + filterRule + " on change "
                + change.getId() + " of " + parentState.getProject().getName(), err);
          } catch (RuntimeException err) {
            return logRuleError("Exception calling " + filterRule + " on change "
                + change.getId() + " of " + parentState.getProject().getName(), err);
          }
        }

        parentState = parentState.getParentState();
        childEnv = parentEnv;
      }
    } finally {
      env.close();
    }

    if (results.isEmpty()) {
      // This should never occur. A well written submit rule will always produce
      // at least one result informing the caller of the labels that are
      // required for this change to be submittable. Each label will indicate
      // whether or not that is actually possible given the permissions.
      log.error("Submit rule " + submitRule + " for change " + change.getId()
          + " of " + getProject().getName() + " has no solution.");
      return ruleError("Project submit rule has no solution");
    }

    return resultsToSubmitRecord(submitRule, results);
  }

  /**
   * Convert the results from Prolog Cafe's format to Gerrit's common format.
   *
   * can_submit/1 terminates when an ok(P) record is found. Therefore walk
   * the results backwards, using only that ok(P) record if it exists. This
   * skips partial results that occur early in the output. Later after the loop
   * the out collection is reversed to restore it to the original ordering.
   */
  public List<SubmitRecord> resultsToSubmitRecord(Term submitRule, List<Term> results) {
    List<SubmitRecord> out = new ArrayList<SubmitRecord>(results.size());
    for (int resultIdx = results.size() - 1; 0 <= resultIdx; resultIdx--) {
      Term submitRecord = results.get(resultIdx);
      SubmitRecord rec = new SubmitRecord();
      out.add(rec);

      if (!submitRecord.isStructure() || 1 != submitRecord.arity()) {
        return logInvalidResult(submitRule, submitRecord);
      }

      if ("ok".equals(submitRecord.name())) {
        rec.status = SubmitRecord.Status.OK;

      } else if ("not_ready".equals(submitRecord.name())) {
        rec.status = SubmitRecord.Status.NOT_READY;

      } else {
        return logInvalidResult(submitRule, submitRecord);
      }

      // Unpack the one argument. This should also be a structure with one
      // argument per label that needs to be reported on to the caller.
      //
      submitRecord = submitRecord.arg(0);

      if (!submitRecord.isStructure()) {
        return logInvalidResult(submitRule, submitRecord);
      }

      rec.labels = new ArrayList<SubmitRecord.Label> (submitRecord.arity());

      for (Term state : ((StructureTerm) submitRecord).args()) {
        if (!state.isStructure() || 2 != state.arity() || !"label".equals(state.name())) {
          return logInvalidResult(submitRule, submitRecord);
        }

        SubmitRecord.Label lbl = new SubmitRecord.Label();
        rec.labels.add(lbl);

        lbl.label = state.arg(0).name();
        Term status = state.arg(1);

        if ("ok".equals(status.name())) {
          lbl.status = SubmitRecord.Label.Status.OK;
          appliedBy(lbl, status);

        } else if ("reject".equals(status.name())) {
          lbl.status = SubmitRecord.Label.Status.REJECT;
          appliedBy(lbl, status);

        } else if ("need".equals(status.name())) {
          lbl.status = SubmitRecord.Label.Status.NEED;

        } else if ("may".equals(status.name())) {
          lbl.status = SubmitRecord.Label.Status.MAY;

        } else if ("impossible".equals(status.name())) {
          lbl.status = SubmitRecord.Label.Status.IMPOSSIBLE;

        } else {
          return logInvalidResult(submitRule, submitRecord);
        }
      }

      if (rec.status == SubmitRecord.Status.OK) {
        break;
      }
    }
    Collections.reverse(out);

    return out;
  }

  private List<SubmitRecord> logInvalidResult(Term rule, Term record) {
    return logRuleError("Submit rule " + rule + " for change " + change.getId()
        + " of " + getProject().getName() + " output invalid result: " + record);
  }

  private List<SubmitRecord> logRuleError(String err, Exception e) {
    log.error(err, e);
    return ruleError("Error evaluating project rules, check server log");
  }

  private List<SubmitRecord> logRuleError(String err) {
    log.error(err);
    return ruleError("Error evaluating project rules, check server log");
  }

  private List<SubmitRecord> ruleError(String err) {
    SubmitRecord rec = new SubmitRecord();
    rec.status = SubmitRecord.Status.RULE_ERROR;
    rec.errorMessage = err;
    return Collections.singletonList(rec);
  }

  private void appliedBy(SubmitRecord.Label label, Term status) {
    if (status.isStructure() && status.arity() == 1) {
      Term who = status.arg(0);
      if (isUser(who)) {
        label.appliedBy = new Account.Id(((IntegerTerm) who.arg(0)).intValue());
      }
    }
  }

  private boolean isDraftVisible(ReviewDb db, ChangeData cd)
      throws OrmException {
    return isOwner() || isReviewer(db, cd);
  }

  private static boolean isUser(Term who) {
    return who.isStructure()
        && who.arity() == 1
        && who.name().equals("user")
        && who.arg(0).isInteger();
  }

  public static Term toListTerm(List<Term> terms) {
    Term list = Prolog.Nil;
    for (int i = terms.size() - 1; i >= 0; i--) {
      list = new ListTerm(terms.get(i), list);
    }
    return list;
  }
}
