// 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.RemovalNotification;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.events.GitReferenceUpdatedListener;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.server.cache.CacheModule;
import com.google.gerrit.server.cache.CacheRemovalListener;
import com.google.gerrit.server.config.AllUsersName;
import com.google.inject.Inject;
import com.google.inject.Module;
import com.google.inject.Singleton;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;

public interface PathOwnersEntriesCache {
  String CACHE_NAME = "path_owners_entries";

  static Module module() {
    return new CacheModule() {
      @Override
      protected void configure() {
        cache(CACHE_NAME, Key.class, PathOwnersEntry.class);
        bind(PathOwnersEntriesCache.class).to(PathOwnersEntriesCacheImpl.class);
        DynamicSet.bind(binder(), GitReferenceUpdatedListener.class)
            .to(OwnersRefUpdateListener.class);
        DynamicSet.bind(binder(), CacheRemovalListener.class).to(OwnersCacheRemovalListener.class);
      }
    };
  }

  PathOwnersEntry get(String project, String branch, String path, Callable<PathOwnersEntry> loader)
      throws ExecutionException;

  void invalidate(String project, String branch);

  void invalidateIndexKey(Key key);

  class Key {
    final String project;
    final String branch;
    final String path;

    Key(String project, String branch, String path) {
      this.project = project;
      this.branch = branch;
      this.path = path;
    }

    @Override
    public int hashCode() {
      return Objects.hash(branch, path, project);
    }

    @Override
    public boolean equals(Object obj) {
      if (this == obj) {
        return true;
      }

      if (obj == null) {
        return false;
      }

      if (getClass() != obj.getClass()) {
        return false;
      }

      Key other = (Key) obj;
      return Objects.equals(branch, other.branch)
          && Objects.equals(path, other.path)
          && Objects.equals(project, other.project);
    }

    @Override
    public String toString() {
      StringBuilder builder = new StringBuilder();
      builder.append("Key [project=");
      builder.append(project);
      builder.append(", branch=");
      builder.append(branch);
      builder.append(", path=");
      builder.append(path);
      builder.append("]");
      return builder.toString();
    }
  }

  @Singleton
  class OwnersRefUpdateListener implements GitReferenceUpdatedListener {
    private final PathOwnersEntriesCache cache;
    private final String allUsersName;

    @Inject
    OwnersRefUpdateListener(PathOwnersEntriesCache cache, AllUsersName allUsersName) {
      this.cache = cache;
      this.allUsersName = allUsersName.get();
    }

    @Override
    public void onGitReferenceUpdated(Event event) {
      if (supportedEvent(allUsersName, event)) {
        cache.invalidate(event.getProjectName(), event.getRefName());
      }
    }

    static boolean supportedEvent(String allUsersName, Event event) {
      String refName = event.getRefName();
      return !allUsersName.equals(event.getProjectName())
          && (refName.equals(RefNames.REFS_CONFIG) || !RefNames.isGerritRef(refName));
    }
  }

  @Singleton
  class OwnersCacheRemovalListener implements CacheRemovalListener<Key, PathOwnersEntry> {
    private final PathOwnersEntriesCache cache;
    private final String cacheName;

    @Inject
    OwnersCacheRemovalListener(@PluginName String pluginName, PathOwnersEntriesCache cache) {
      this.cache = cache;
      this.cacheName = String.format("%s.%s", pluginName, CACHE_NAME);
    }

    @Override
    public void onRemoval(
        String pluginName,
        String cacheName,
        RemovalNotification<Key, PathOwnersEntry> notification) {
      if (!this.cacheName.equals(cacheName)) {
        return;
      }

      cache.invalidateIndexKey(notification.getKey());
    }
  }
}
