// Copyright (C) 2008 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.client.rpc;

import com.google.gerrit.client.data.ProjectCache;
import com.google.gerrit.client.reviewdb.Account;
import com.google.gerrit.client.reviewdb.AccountGroup;
import com.google.gerrit.client.reviewdb.ApprovalCategory;
import com.google.gerrit.client.reviewdb.Change;
import com.google.gerrit.client.reviewdb.Project;
import com.google.gerrit.client.reviewdb.ProjectRight;
import com.google.gerrit.client.reviewdb.ReviewDb;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwtorm.client.OrmException;

import java.util.Set;

/** Support for services which require a {@link ReviewDb} instance. */
public class BaseServiceImplementation {
  /**
   * Executes <code>action.run</code> with an active ReviewDb connection.
   * <p>
   * A database handle is automatically opened and closed around the action's
   * {@link Action#run(ReviewDb)} method. OrmExceptions are caught and passed
   * into the onFailure method of the callback.
   * 
   * @param <T> type of result the callback expects.
   * @param callback the callback that will receive the result.
   * @param action the action logic to perform.
   */
  protected <T> void run(final AsyncCallback<T> callback, final Action<T> action) {
    try {
      final ReviewDb db = Common.getSchemaFactory().open();
      final T r;
      try {
        r = action.run(db);
      } finally {
        db.close();
      }
      if (r != null) {
        callback.onSuccess(r);
      }
    } catch (OrmException e) {
      if (e.getCause() instanceof Failure) {
        callback.onFailure(e.getCause().getCause());

      } else if (e.getCause() instanceof CorruptEntityException) {
        callback.onFailure(e.getCause());

      } else if (e.getCause() instanceof NoSuchEntityException) {
        callback.onFailure(e.getCause());

      } else if (e.getCause() instanceof NoDifferencesException) {
        callback.onFailure(e.getCause());

      } else {
        callback.onFailure(e);
      }
    } catch (Failure e) {
      callback.onFailure(e.getCause());
    }
  }

  /** Throws NoSuchEntityException if the caller cannot access the project. */
  public static void assertCanRead(final Change change) throws Failure {
    if (!canRead(change)) {
      throw new Failure(new NoSuchEntityException());
    }
  }

  /** Throws NoSuchEntityException if the caller cannot access the project. */
  public static void assertCanRead(final Project.NameKey projectKey)
      throws Failure {
    if (!canRead(projectKey)) {
      throw new Failure(new NoSuchEntityException());
    }
  }

  /** Return true if the current user can read this change's project. */
  public static boolean canRead(final Change change) {
    return change != null && canRead(change.getDest().getParentKey());
  }

  /** Return true if the current user can read this project, and its contents. */
  public static boolean canRead(final Project.NameKey projectKey) {
    return canRead(Common.getAccountId(), projectKey);
  }

  public static boolean canRead(final Account.Id who,
      final Project.NameKey projectKey) {
    final ProjectCache.Entry e = Common.getProjectCache().get(projectKey);
    if (e == null) {
      // Unexpected, a project disappearing. But claim its not available.
      //
      return false;
    }
    final Set<AccountGroup.Id> myGroups = Common.getGroupCache().getEffectiveGroups(who);
    return canPerform(myGroups, e, ApprovalCategory.READ, (short) 1, true);
  }

  public static boolean canPerform(final Set<AccountGroup.Id> myGroups,
      final ProjectCache.Entry e, final ApprovalCategory.Id actionId,
      final short requireValue, final boolean assumeOwner) {
    if (assumeOwner && myGroups.contains(e.getProject().getOwnerGroupId())) {
      // Ownership implies full access.
      //
      return true;
    }

    int val = Integer.MIN_VALUE;
    for (final ProjectRight pr : e.getRights()) {
      if (actionId.equals(pr.getApprovalCategoryId())
          && myGroups.contains(pr.getAccountGroupId())) {
        if (val < 0 && pr.getMaxValue() > 0) {
          // If one of the user's groups had denied them access, but
          // this group grants them access, prefer the grant over
          // the denial. We have to break the tie somehow and we
          // prefer being "more open" to being "more closed".
          //
          val = pr.getMaxValue();
        } else {
          // Otherwise we use the largest value we can get.
          //
          val = Math.max(pr.getMaxValue(), val);
        }
      }
    }
    if (val == Integer.MIN_VALUE) {
      for (final ProjectRight pr : Common.getProjectCache().getWildcardRights()) {
        if (actionId.equals(pr.getApprovalCategoryId())
            && myGroups.contains(pr.getAccountGroupId())) {
          val = Math.max(pr.getMaxValue(), val);
        }
      }
    }

    return val >= requireValue;
  }

  /** Exception whose cause is passed into onFailure. */
  public static class Failure extends Exception {
    public Failure(final Throwable why) {
      super(why);
    }
  }

  /** Arbitrary action to run with a database connection. */
  public static interface Action<T> {
    /**
     * Perform this action, returning the onSuccess value.
     * 
     * @param db an open database handle to be used by this connection.
     * @return he value to pass to {@link AsyncCallback#onSuccess(Object)}.
     * @throws OrmException any schema based action failed.
     * @throws Failure cause is given to
     *         {@link AsyncCallback#onFailure(Throwable)}.
     */
    T run(ReviewDb db) throws OrmException, Failure;
  }
}
