// Copyright (C) 2023 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.googlesource.gerrit.owners.common;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.inject.name.Named;
import java.time.Duration;
import java.util.Collection;
import java.util.Optional;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;

@Singleton
class PathOwnersEntriesCacheImpl implements PathOwnersEntriesCache {

  private final Cache<Key, Optional<OwnersConfig>> cache;
  private final Multimap<String, Key> keysIndex;
  private final LoadingCache<String, Object> keyLocks;

  @Inject
  PathOwnersEntriesCacheImpl(@Named(CACHE_NAME) Cache<Key, Optional<OwnersConfig>> cache) {
    this.cache = cache;
    this.keysIndex = HashMultimap.create();
    this.keyLocks =
        CacheBuilder.newBuilder()
            .expireAfterAccess(Duration.ofMinutes(10L))
            .build(CacheLoader.from(Object::new));
  }

  @Override
  public Optional<OwnersConfig> get(
      String project, String branch, String path, Callable<Optional<OwnersConfig>> loader)
      throws ExecutionException {
    Key key = new Key(project, branch, path);
    return cache.get(
        key,
        () -> {
          Optional<OwnersConfig> entry = loader.call();
          String indexKey = indexKey(project, branch);
          synchronized (keyLocks.getUnchecked(indexKey)) {
            keysIndex.put(indexKey, key);
          }
          return entry;
        });
  }

  @Override
  public void invalidate(String project, String branch) {
    String indexKey = indexKey(project, branch);
    Collection<Key> keysToInvalidate;

    synchronized (keyLocks.getUnchecked(indexKey)) {
      keysToInvalidate = keysIndex.removeAll(indexKey);
    }

    keysToInvalidate.forEach(cache::invalidate);
  }

  @Override
  public void invalidateIndexKey(Key key) {
    String indexKey = indexKey(key.project, key.branch);

    synchronized (keyLocks.getUnchecked(indexKey)) {
      Collection<Key> values = keysIndex.asMap().get(indexKey);
      if (values != null) {
        values.remove(key);
      }
    }
  }

  private String indexKey(String project, String branch) {
    return new StringBuilder(project).append('@').append(branch).toString();
  }
}
