// 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.account;

import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.entities.InternalGroup;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.proto.Protos;
import com.google.gerrit.server.cache.CacheModule;
import com.google.gerrit.server.cache.proto.Cache;
import com.google.gerrit.server.cache.serialize.CacheSerializer;
import com.google.gerrit.server.cache.serialize.ObjectIdConverter;
import com.google.gerrit.server.cache.serialize.ProtobufSerializer;
import com.google.gerrit.server.cache.serialize.entities.InternalGroupSerializer;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.group.db.Groups;
import com.google.gerrit.server.logging.Metadata;
import com.google.gerrit.server.logging.TraceContext;
import com.google.gerrit.server.logging.TraceContext.TraceTimer;
import com.google.gerrit.server.query.group.InternalGroupQuery;
import com.google.inject.Inject;
import com.google.inject.Module;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Named;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import org.bouncycastle.util.Strings;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;

/** Tracks group objects in memory for efficient access. */
@Singleton
public class GroupCacheImpl implements GroupCache {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private static final String BYID_NAME = "groups";
  private static final String BYNAME_NAME = "groups_byname";
  private static final String BYUUID_NAME = "groups_byuuid";
  private static final String BYUUID_NAME_PERSISTED = "groups_byuuid_persisted";

  public static Module module() {
    return new CacheModule() {
      @Override
      protected void configure() {
        cache(BYID_NAME, AccountGroup.Id.class, new TypeLiteral<Optional<InternalGroup>>() {})
            .maximumWeight(Long.MAX_VALUE)
            .loader(ByIdLoader.class);

        cache(BYNAME_NAME, String.class, new TypeLiteral<Optional<InternalGroup>>() {})
            .maximumWeight(Long.MAX_VALUE)
            .loader(ByNameLoader.class);

        // We split the group cache into two parts for performance reasons:
        // 1) An in-memory part that has only the group ref uuid as key.
        // 2) A persisted part that has the group ref uuid and sha1 of the ref as key.
        //
        // When loading dashboards or returning change query results we potentially
        // need to access many groups.
        // We want the persisted cache to be immutable and we want it to be impossible that a
        // value for a given key is out of date. We therefore require the sha-1 in the key. That
        // is in line with the rest of the caches in Gerrit.
        //
        // Splitting the cache into two chunks internally in this class allows us to retain
        // the existing performance guarantees of not requiring reads for the repo for values
        // cached in-memory but also to persist the cache which leads to a much improved
        // cold-start behavior and in-memory miss latency.

        cache(BYUUID_NAME, String.class, new TypeLiteral<Optional<InternalGroup>>() {})
            .maximumWeight(Long.MAX_VALUE)
            .loader(ByUUIDInMemoryLoader.class);

        persist(
                BYUUID_NAME_PERSISTED,
                Cache.GroupKeyProto.class,
                new TypeLiteral<InternalGroup>() {})
            .loader(PersistedByUUIDLoader.class)
            .keySerializer(new ProtobufSerializer<>(Cache.GroupKeyProto.parser()))
            .valueSerializer(PersistedInternalGroupSerializer.INSTANCE)
            .diskLimit(1 << 30) // 1 GiB
            .version(1)
            .maximumWeight(0);

        bind(GroupCacheImpl.class);
        bind(GroupCache.class).to(GroupCacheImpl.class);
      }
    };
  }

  private final LoadingCache<AccountGroup.Id, Optional<InternalGroup>> byId;
  private final LoadingCache<String, Optional<InternalGroup>> byName;
  private final LoadingCache<String, Optional<InternalGroup>> byUUID;

  @Inject
  GroupCacheImpl(
      @Named(BYID_NAME) LoadingCache<AccountGroup.Id, Optional<InternalGroup>> byId,
      @Named(BYNAME_NAME) LoadingCache<String, Optional<InternalGroup>> byName,
      @Named(BYUUID_NAME) LoadingCache<String, Optional<InternalGroup>> byUUID) {
    this.byId = byId;
    this.byName = byName;
    this.byUUID = byUUID;
  }

  @Override
  public Optional<InternalGroup> get(AccountGroup.Id groupId) {
    try {
      return byId.get(groupId);
    } catch (ExecutionException e) {
      logger.atWarning().withCause(e).log("Cannot load group %s", groupId);
      return Optional.empty();
    }
  }

  @Override
  public Optional<InternalGroup> get(AccountGroup.NameKey name) {
    if (name == null) {
      return Optional.empty();
    }
    try {
      return byName.get(name.get());
    } catch (ExecutionException e) {
      logger.atWarning().withCause(e).log("Cannot look up group %s by name", name.get());
      return Optional.empty();
    }
  }

  @Override
  public Optional<InternalGroup> get(AccountGroup.UUID groupUuid) {
    if (groupUuid == null) {
      return Optional.empty();
    }

    try {
      return byUUID.get(groupUuid.get());
    } catch (ExecutionException e) {
      logger.atWarning().withCause(e).log("Cannot look up group %s by uuid", groupUuid.get());
      return Optional.empty();
    }
  }

  @Override
  public void evict(AccountGroup.Id groupId) {
    if (groupId != null) {
      logger.atFine().log("Evict group %s by ID", groupId.get());
      byId.invalidate(groupId);
    }
  }

  @Override
  public void evict(AccountGroup.NameKey groupName) {
    if (groupName != null) {
      logger.atFine().log("Evict group '%s' by name", groupName.get());
      byName.invalidate(groupName.get());
    }
  }

  @Override
  public void evict(AccountGroup.UUID groupUuid) {
    if (groupUuid != null) {
      logger.atFine().log("Evict group %s by UUID", groupUuid.get());
      byUUID.invalidate(groupUuid.get());
    }
  }

  static class ByIdLoader extends CacheLoader<AccountGroup.Id, Optional<InternalGroup>> {
    private final Provider<InternalGroupQuery> groupQueryProvider;

    @Inject
    ByIdLoader(Provider<InternalGroupQuery> groupQueryProvider) {
      this.groupQueryProvider = groupQueryProvider;
    }

    @Override
    public Optional<InternalGroup> load(AccountGroup.Id key) throws Exception {
      try (TraceTimer ignored =
          TraceContext.newTimer(
              "Loading group by ID", Metadata.builder().groupId(key.get()).build())) {
        return groupQueryProvider.get().byId(key);
      }
    }
  }

  static class ByNameLoader extends CacheLoader<String, Optional<InternalGroup>> {
    private final Provider<InternalGroupQuery> groupQueryProvider;

    @Inject
    ByNameLoader(Provider<InternalGroupQuery> groupQueryProvider) {
      this.groupQueryProvider = groupQueryProvider;
    }

    @Override
    public Optional<InternalGroup> load(String name) throws Exception {
      try (TraceTimer ignored =
          TraceContext.newTimer(
              "Loading group by name", Metadata.builder().groupName(name).build())) {
        return groupQueryProvider.get().byName(AccountGroup.nameKey(name));
      }
    }
  }

  static class ByUUIDInMemoryLoader extends CacheLoader<String, Optional<InternalGroup>> {
    private final LoadingCache<Cache.GroupKeyProto, InternalGroup> persistedCache;
    private final GitRepositoryManager repoManager;
    private final AllUsersName allUsersName;

    @Inject
    ByUUIDInMemoryLoader(
        @Named(BYUUID_NAME_PERSISTED)
            LoadingCache<Cache.GroupKeyProto, InternalGroup> persistedCache,
        GitRepositoryManager repoManager,
        AllUsersName allUsersName) {
      this.persistedCache = persistedCache;
      this.repoManager = repoManager;
      this.allUsersName = allUsersName;
    }

    @Override
    public Optional<InternalGroup> load(String uuid) throws Exception {
      try (TraceTimer ignored =
              TraceContext.newTimer(
                  "Loading group from serialized cache",
                  Metadata.builder().groupUuid(uuid).build());
          Repository allUsers = repoManager.openRepository(allUsersName)) {
        String ref = RefNames.refsGroups(AccountGroup.uuid(uuid));
        Ref sha1 = allUsers.exactRef(ref);
        if (sha1 == null) {
          return Optional.empty();
        }
        Cache.GroupKeyProto key =
            Cache.GroupKeyProto.newBuilder()
                .setUuid(uuid)
                .setRevision(ObjectIdConverter.create().toByteString(sha1.getObjectId()))
                .build();
        return Optional.of(persistedCache.get(key));
      }
    }
  }

  static class PersistedByUUIDLoader extends CacheLoader<Cache.GroupKeyProto, InternalGroup> {
    private final Groups groups;

    @Inject
    PersistedByUUIDLoader(Groups groups) {
      this.groups = groups;
    }

    @Override
    public InternalGroup load(Cache.GroupKeyProto key) throws Exception {
      try (TraceTimer ignored =
          TraceContext.newTimer(
              "Loading group by UUID", Metadata.builder().groupUuid(key.getUuid()).build())) {
        ObjectId sha1 = ObjectIdConverter.create().fromByteString(key.getRevision());
        Optional<InternalGroup> loadedGroup =
            groups.getGroup(AccountGroup.uuid(key.getUuid()), sha1);
        if (!loadedGroup.isPresent()) {
          throw new IllegalStateException(
              String.format(
                  "group %s should have the sha-1 %s, but " + "it was not found",
                  key.getUuid(), sha1.getName()));
        }
        return loadedGroup.get();
      }
    }
  }

  private enum PersistedInternalGroupSerializer implements CacheSerializer<InternalGroup> {
    INSTANCE;

    @Override
    public byte[] serialize(InternalGroup value) {
      if (value == null) {
        return new byte[0];
      }
      return Protos.toByteArray(InternalGroupSerializer.serialize(value));
    }

    @Override
    public InternalGroup deserialize(byte[] in) {
      if (Strings.fromByteArray(in).isEmpty()) {
        return null;
      }
      return InternalGroupSerializer.deserialize(
          Protos.parseUnchecked(Cache.InternalGroupProto.parser(), in));
    }
  }
}
