// Copyright (C) 2013 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.extensions.webui;

import static com.google.gerrit.extensions.conditions.BooleanCondition.and;
import static com.google.gerrit.extensions.conditions.BooleanCondition.or;
import static java.util.stream.Collectors.toList;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Predicate;
import com.google.common.collect.Streams;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.extensions.api.access.GlobalOrPluginPermission;
import com.google.gerrit.extensions.conditions.BooleanCondition;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.registration.PluginName;
import com.google.gerrit.extensions.restapi.RestCollection;
import com.google.gerrit.extensions.restapi.RestResource;
import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.extensions.webui.PrivateInternals_UiActionDescription;
import com.google.gerrit.extensions.webui.UiAction;
import com.google.gerrit.extensions.webui.UiAction.Description;
import com.google.gerrit.metrics.Description.Units;
import com.google.gerrit.metrics.Field;
import com.google.gerrit.metrics.MetricMaker;
import com.google.gerrit.metrics.Timer1;
import com.google.gerrit.server.permissions.GlobalPermission;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendCondition;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

@Singleton
public class UiActions {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  public static Predicate<UiAction.Description> enabled() {
    return UiAction.Description::isEnabled;
  }

  private final PermissionBackend permissionBackend;
  private final Timer1<String> uiActionLatency;

  @Inject
  UiActions(PermissionBackend permissionBackend, MetricMaker metricMaker) {
    this.permissionBackend = permissionBackend;
    this.uiActionLatency =
        metricMaker.newTimer(
            "http/server/rest_api/ui_actions/latency",
            new com.google.gerrit.metrics.Description("Latency for RestView#getDescription calls")
                .setCumulative()
                .setUnit(Units.MILLISECONDS),
            Field.ofString("view"));
  }

  public <R extends RestResource> Iterable<UiAction.Description> from(
      RestCollection<?, R> collection, R resource) {
    return from(collection.views(), resource);
  }

  public <R extends RestResource> Iterable<UiAction.Description> from(
      DynamicMap<RestView<R>> views, R resource) {
    List<UiAction.Description> descs =
        Streams.stream(views)
            .map(e -> describe(e, resource))
            .filter(Objects::nonNull)
            .collect(toList());

    List<PermissionBackendCondition> conds =
        Streams.concat(
                descs.stream().flatMap(u -> Streams.stream(visibleCondition(u))),
                descs.stream().flatMap(u -> Streams.stream(enabledCondition(u))))
            .collect(toList());

    evaluatePermissionBackendConditions(permissionBackend, conds);

    return descs.stream().filter(Description::isVisible).collect(toList());
  }

  @VisibleForTesting
  static void evaluatePermissionBackendConditions(
      PermissionBackend perm, List<PermissionBackendCondition> conds) {
    Map<PermissionBackendCondition, PermissionBackendCondition> dedupedConds =
        new HashMap<>(conds.size());
    for (PermissionBackendCondition cond : conds) {
      dedupedConds.put(cond, cond);
    }
    perm.bulkEvaluateTest(dedupedConds.keySet());
    for (PermissionBackendCondition cond : conds) {
      cond.set(dedupedConds.get(cond).value());
    }
  }

  private static Iterable<PermissionBackendCondition> visibleCondition(Description u) {
    return u.getVisibleCondition().reduce().children(PermissionBackendCondition.class);
  }

  private static Iterable<PermissionBackendCondition> enabledCondition(Description u) {
    return u.getEnabledCondition().reduce().children(PermissionBackendCondition.class);
  }

  @Nullable
  private <R extends RestResource> UiAction.Description describe(
      DynamicMap.Entry<RestView<R>> e, R resource) {
    int d = e.getExportName().indexOf('.');
    if (d < 0) {
      return null;
    }

    RestView<R> view;
    try {
      view = e.getProvider().get();
    } catch (RuntimeException err) {
      logger.atSevere().withCause(err).log(
          "error creating view %s.%s", e.getPluginName(), e.getExportName());
      return null;
    }

    if (!(view instanceof UiAction)) {
      return null;
    }

    String name = e.getExportName().substring(d + 1);
    UiAction.Description dsc;
    try (Timer1.Context ignored = uiActionLatency.start(name)) {
      dsc = ((UiAction<R>) view).getDescription(resource);
    }

    if (dsc == null) {
      return null;
    }

    Set<GlobalOrPluginPermission> globalRequired;
    try {
      globalRequired = GlobalPermission.fromAnnotation(e.getPluginName(), view.getClass());
    } catch (PermissionBackendException err) {
      logger.atSevere().withCause(err).log(
          "exception testing view %s.%s", e.getPluginName(), e.getExportName());
      return null;
    }
    if (!globalRequired.isEmpty()) {
      PermissionBackend.WithUser withUser = permissionBackend.currentUser();
      Iterator<GlobalOrPluginPermission> i = globalRequired.iterator();
      BooleanCondition p = withUser.testCond(i.next());
      while (i.hasNext()) {
        p = or(p, withUser.testCond(i.next()));
      }
      dsc.setVisible(and(p, dsc.getVisibleCondition()));
    }

    PrivateInternals_UiActionDescription.setMethod(dsc, e.getExportName().substring(0, d));
    PrivateInternals_UiActionDescription.setId(
        dsc, PluginName.GERRIT.equals(e.getPluginName()) ? name : e.getPluginName() + '~' + name);
    return dsc;
  }
}
