// 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 ProjectConfig.Factory projectConfigFactory;
  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,
      ProjectConfig.Factory projectConfigFactory,
      ProjectCache projectCache,
      WorkQueue queue) {
    this.pluginName = pluginName;
    this.downloadCommands = downloadCommands;
    this.metaDataUpdateFactory = metaDataUpdateFactory;
    this.projectConfigFactory = projectConfigFactory;
    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 =
            projectConfigFactory.read(
                metaDataUpdateFactory.create(p), ObjectId.fromString(event.getOldObjectId()));
        PluginConfig oldPluginCfg = oldCfg.getPluginConfig(pluginName);
        for (String name : oldPluginCfg.getNames()) {
          removeCommand(p, name);
        }

        ProjectConfig newCfg =
            projectConfigFactory.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;
  }
}
