// 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.googlesource.gerrit.plugins.download.command.project;

import com.google.common.collect.Maps;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.config.DownloadCommand;
import com.google.gerrit.extensions.events.GitReferenceUpdatedListener;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.registration.PrivateInternals_DynamicMapImpl;
import com.google.gerrit.extensions.registration.RegistrationHandle;
import com.google.gerrit.server.config.PluginConfig;
import com.google.gerrit.server.git.WorkQueue;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectConfig;
import com.google.gerrit.server.project.ProjectState;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.ObjectId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Singleton
public class DownloadCommandUpdater implements GitReferenceUpdatedListener, LifecycleListener {
  private static final Logger log = LoggerFactory.getLogger(DownloadCommandUpdater.class);

  private final String pluginName;
  private final DynamicMap<DownloadCommand> downloadCommands;
  private final MetaDataUpdate.Server metaDataUpdateFactory;
  private final ProjectCache projectCache;
  private final Map<String, ProjectDownloadCommand> projectDownloadCommands;
  private final Map<String, RegistrationHandle> registrationHandles;
  private final ScheduledExecutorService executor;

  @Inject
  DownloadCommandUpdater(
      @PluginName String pluginName,
      DynamicMap<DownloadCommand> downloadCommands,
      MetaDataUpdate.Server metaDataUpdateFactory,
      ProjectCache projectCache,
      WorkQueue queue) {
    this.pluginName = pluginName;
    this.downloadCommands = downloadCommands;
    this.metaDataUpdateFactory = metaDataUpdateFactory;
    this.projectCache = projectCache;
    this.projectDownloadCommands = Maps.newHashMap();
    this.registrationHandles = Maps.newHashMap();
    this.executor = queue.createQueue(1, "download-command-updater");
  }

  @Override
  public void start() {
    executor.submit(
        new Runnable() {
          @Override
          public void run() {
            for (Project.NameKey p : projectCache.all()) {
              ProjectState projectState = projectCache.get(p);
              if (projectState != null) {
                PluginConfig cfg = projectState.getConfig().getPluginConfig(pluginName);
                for (String name : cfg.getNames()) {
                  installCommand(projectState.getProject().getNameKey(), name, cfg.getString(name));
                }
              }
            }
          }
        });
  }

  @Override
  public void stop() {
    for (RegistrationHandle rh : registrationHandles.values()) {
      rh.remove();
    }
    registrationHandles.clear();
    projectDownloadCommands.clear();
  }

  @Override
  public void onGitReferenceUpdated(Event event) {
    if (event.getRefName().equals(RefNames.REFS_CONFIG)) {
      Project.NameKey p = new Project.NameKey(event.getProjectName());
      try {
        ProjectConfig oldCfg =
            ProjectConfig.read(
                metaDataUpdateFactory.create(p), ObjectId.fromString(event.getOldObjectId()));
        PluginConfig oldPluginCfg = oldCfg.getPluginConfig(pluginName);
        for (String name : oldPluginCfg.getNames()) {
          removeCommand(p, name);
        }

        ProjectConfig newCfg =
            ProjectConfig.read(
                metaDataUpdateFactory.create(p), ObjectId.fromString(event.getNewObjectId()));
        PluginConfig newPluginCfg = newCfg.getPluginConfig(pluginName);
        for (String name : newPluginCfg.getNames()) {
          installCommand(p, name, newPluginCfg.getString(name));
        }
      } catch (IOException | ConfigInvalidException e) {
        log.error(
            "Failed to update download commands for project "
                + p.get()
                + " on update of "
                + RefNames.REFS_CONFIG,
            e);
      }
    }
  }

  private void installCommand(final Project.NameKey p, String name, final String command) {
    ProjectDownloadCommand dc = projectDownloadCommands.get(name);
    if (dc != null) {
      dc.add(p, command);
    } else {
      dc = new ProjectDownloadCommand(projectCache, p, command);
      projectDownloadCommands.put(name, dc);
      registrationHandles.put(name, map().put(pluginName, name.replaceAll("-", " "), provider(dc)));
    }
  }

  private Provider<DownloadCommand> provider(final DownloadCommand dc) {
    return new Provider<DownloadCommand>() {
      @Override
      public DownloadCommand get() {
        return dc;
      }
    };
  }

  private void removeCommand(Project.NameKey p, String name) {
    ProjectDownloadCommand dc = projectDownloadCommands.get(name);
    dc.remove(p);
    if (!dc.hasCommands()) {
      registrationHandles.remove(name).remove();
    }
  }

  private PrivateInternals_DynamicMapImpl<DownloadCommand> map() {
    return (PrivateInternals_DynamicMapImpl<DownloadCommand>) downloadCommands;
  }
}
