// Copyright (C) 2014 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.serviceuser;

import com.google.common.base.Strings;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.annotations.RequiresCapability;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.config.ConfigResource;
import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.gerrit.server.config.SitePaths;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.googlesource.gerrit.plugins.serviceuser.PutConfig.Input;
import java.io.IOException;
import java.util.List;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;

@RequiresCapability(GlobalCapability.ADMINISTRATE_SERVER)
@Singleton
class PutConfig implements RestModifyView<ConfigResource, Input> {
  public static class Input {
    public String info;
    public String onSuccess;
    public Boolean allowEmail;
    public Boolean allowHttpPassword;
    public Boolean allowOwner;
    public Boolean createNotes;
    public Boolean createNotesAsync;
    public List<String> blockedNames;
    public List<String> groups;
  }

  private final PluginConfigFactory cfgFactory;
  private final SitePaths sitePaths;
  private final String pluginName;
  private final GroupCache groupCache;

  @Inject
  PutConfig(
      PluginConfigFactory cfgFactory,
      SitePaths sitePaths,
      @PluginName String pluginName,
      GroupCache groupCache) {
    this.cfgFactory = cfgFactory;
    this.sitePaths = sitePaths;
    this.pluginName = pluginName;
    this.groupCache = groupCache;
  }

  @Override
  public Response<String> apply(ConfigResource rsrc, Input input)
      throws IOException, ConfigInvalidException, UnprocessableEntityException {
    FileBasedConfig cfg = new FileBasedConfig(sitePaths.gerrit_config.toFile(), FS.DETECTED);
    cfg.load();
    if (input.info != null) {
      cfg.setString("plugin", pluginName, "infoMessage", Strings.emptyToNull(input.info));
    }
    if (input.onSuccess != null) {
      cfg.setString("plugin", pluginName, "onSuccessMessage", Strings.emptyToNull(input.onSuccess));
    }
    if (input.allowEmail != null) {
      setBoolean(cfg, "allowEmail", input.allowEmail);
    }
    if (input.allowHttpPassword != null) {
      setBoolean(cfg, "allowHttpPassword", input.allowHttpPassword);
    }
    if (input.allowOwner != null) {
      setBoolean(cfg, "allowOwner", input.allowOwner);
    }
    if (input.createNotes != null) {
      setBoolean(cfg, "createNotes", input.createNotes, true);
    }
    if (input.createNotesAsync != null) {
      setBoolean(cfg, "createNotesAsync", input.createNotesAsync);
    }
    if (input.blockedNames != null) {
      cfg.setStringList("plugin", pluginName, "block", input.blockedNames);
    }
    if (input.groups != null) {
      for (String g : input.groups) {
        if (groupCache.get(new AccountGroup.NameKey(g)) == null) {
          throw new UnprocessableEntityException(String.format("Group %s does not exist.", g));
        }
      }
      cfg.setStringList("plugin", pluginName, "group", input.groups);
    }
    cfg.save();
    cfgFactory.getFromGerritConfig(pluginName, true);
    return Response.<String>ok("OK");
  }

  private void setBoolean(Config cfg, String name, boolean value) {
    setBoolean(cfg, name, value, false);
  }

  private void setBoolean(Config cfg, String name, boolean value, boolean defaultValue) {
    if (value == defaultValue) {
      cfg.unset("plugin", pluginName, name);
    } else {
      cfg.setBoolean("plugin", pluginName, name, value);
    }
  }
}
