// 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.google.gerrit.server.restapi.project;

import static com.google.gerrit.server.project.ProjectConfig.COMMENTLINK;
import static com.google.gerrit.server.project.ProjectConfig.KEY_ENABLED;
import static com.google.gerrit.server.project.ProjectConfig.KEY_LINK;
import static com.google.gerrit.server.project.ProjectConfig.KEY_MATCH;

import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.BooleanProjectConfig;
import com.google.gerrit.entities.Project;
import com.google.gerrit.extensions.api.projects.CommentLinkInput;
import com.google.gerrit.extensions.api.projects.ConfigInfo;
import com.google.gerrit.extensions.api.projects.ConfigInput;
import com.google.gerrit.extensions.api.projects.ConfigValue;
import com.google.gerrit.extensions.api.projects.ProjectConfigEntryType;
import com.google.gerrit.extensions.client.InheritableBoolean;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.EnableSignedPush;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.gerrit.server.config.ProjectConfigEntry;
import com.google.gerrit.server.extensions.webui.UiActions;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.permissions.ProjectPermission;
import com.google.gerrit.server.project.BooleanProjectConfigTransformations;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectConfig;
import com.google.gerrit.server.project.ProjectResource;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.project.ProjectState.Factory;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.Config;

@Singleton
public class PutConfig implements RestModifyView<ProjectResource, ConfigInput> {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private static final Pattern PARAMETER_NAME_PATTERN =
      Pattern.compile("^[a-zA-Z0-9]+[a-zA-Z0-9-]*$");

  private final boolean serverEnableSignedPush;
  private final Provider<MetaDataUpdate.User> metaDataUpdateFactory;
  private final ProjectCache projectCache;
  private final ProjectState.Factory projectStateFactory;
  private final DynamicMap<ProjectConfigEntry> pluginConfigEntries;
  private final PluginConfigFactory cfgFactory;
  private final AllProjectsName allProjects;
  private final UiActions uiActions;
  private final DynamicMap<RestView<ProjectResource>> views;
  private final Provider<CurrentUser> user;
  private final PermissionBackend permissionBackend;
  private final ProjectConfig.Factory projectConfigFactory;

  @Inject
  PutConfig(
      @EnableSignedPush boolean serverEnableSignedPush,
      Provider<MetaDataUpdate.User> metaDataUpdateFactory,
      ProjectCache projectCache,
      Factory projectStateFactory,
      DynamicMap<ProjectConfigEntry> pluginConfigEntries,
      PluginConfigFactory cfgFactory,
      AllProjectsName allProjects,
      UiActions uiActions,
      DynamicMap<RestView<ProjectResource>> views,
      Provider<CurrentUser> user,
      PermissionBackend permissionBackend,
      ProjectConfig.Factory projectConfigFactory) {
    this.serverEnableSignedPush = serverEnableSignedPush;
    this.metaDataUpdateFactory = metaDataUpdateFactory;
    this.projectCache = projectCache;
    this.projectStateFactory = projectStateFactory;
    this.pluginConfigEntries = pluginConfigEntries;
    this.cfgFactory = cfgFactory;
    this.allProjects = allProjects;
    this.uiActions = uiActions;
    this.views = views;
    this.user = user;
    this.permissionBackend = permissionBackend;
    this.projectConfigFactory = projectConfigFactory;
  }

  @Override
  public Response<ConfigInfo> apply(ProjectResource rsrc, ConfigInput input)
      throws RestApiException, PermissionBackendException {
    permissionBackend
        .currentUser()
        .project(rsrc.getNameKey())
        .check(ProjectPermission.WRITE_CONFIG);
    return Response.ok(apply(rsrc.getProjectState(), input));
  }

  public ConfigInfo apply(ProjectState projectState, ConfigInput input)
      throws ResourceNotFoundException, BadRequestException, ResourceConflictException {
    Project.NameKey projectName = projectState.getNameKey();
    if (input == null) {
      throw new BadRequestException("config is required");
    }

    try (MetaDataUpdate md = metaDataUpdateFactory.get().create(projectName)) {
      ProjectConfig projectConfig = projectConfigFactory.read(md);
      projectConfig.updateProject(
          p -> {
            p.setDescription(Strings.emptyToNull(input.description));
            for (BooleanProjectConfig cfg : BooleanProjectConfig.values()) {
              InheritableBoolean val = BooleanProjectConfigTransformations.get(cfg, input);
              if (val != null) {
                p.setBooleanConfig(cfg, val);
              }
            }
            if (input.maxObjectSizeLimit != null) {
              p.setMaxObjectSizeLimit(input.maxObjectSizeLimit);
            }
            if (input.submitType != null) {
              p.setSubmitType(input.submitType);
            }
            if (input.state != null) {
              p.setState(input.state);
            }
          });

      if (input.pluginConfigValues != null) {
        setPluginConfigValues(projectState, projectConfig, input.pluginConfigValues);
      }

      if (input.commentLinks != null) {
        updateCommentLinks(projectConfig, input.commentLinks);
      }

      md.setMessage("Modified project settings\n");
      try {
        projectConfig.commit(md);
        projectCache.evictAndReindex(projectConfig.getProject());
        md.getRepository().setGitwebDescription(projectConfig.getProject().getDescription());
      } catch (IOException e) {
        if (e.getCause() instanceof ConfigInvalidException) {
          throw new ResourceConflictException(
              "Cannot update " + projectName + ": " + e.getCause().getMessage());
        }
        logger.atWarning().withCause(e).log("Failed to update config of project %s.", projectName);
        throw new ResourceConflictException("Cannot update " + projectName);
      }

      ProjectState state = projectStateFactory.create(projectConfigFactory.read(md).getCacheable());
      return ConfigInfoCreator.constructInfo(
          serverEnableSignedPush,
          state,
          user.get(),
          pluginConfigEntries,
          cfgFactory,
          allProjects,
          uiActions,
          views);
    } catch (RepositoryNotFoundException notFound) {
      throw new ResourceNotFoundException(projectName.get(), notFound);
    } catch (ConfigInvalidException err) {
      throw new ResourceConflictException("Cannot read project " + projectName, err);
    } catch (IOException err) {
      throw new ResourceConflictException("Cannot update project " + projectName, err);
    }
  }

  private void setPluginConfigValues(
      ProjectState projectState,
      ProjectConfig projectConfig,
      Map<String, Map<String, ConfigValue>> pluginConfigValues)
      throws BadRequestException {
    for (Map.Entry<String, Map<String, ConfigValue>> e : pluginConfigValues.entrySet()) {
      String pluginName = e.getKey();
      for (Map.Entry<String, ConfigValue> v : e.getValue().entrySet()) {
        ProjectConfigEntry projectConfigEntry = pluginConfigEntries.get(pluginName, v.getKey());
        if (projectConfigEntry != null) {
          if (!PARAMETER_NAME_PATTERN.matcher(v.getKey()).matches()) {
            // TODO check why we have this restriction
            logger.atWarning().log(
                "Parameter name '%s' must match '%s'",
                v.getKey(), PARAMETER_NAME_PATTERN.pattern());
            continue;
          }
          String oldValue = projectConfig.getPluginConfig(pluginName).getString(v.getKey());
          String value = v.getValue().value;
          if (projectConfigEntry.getType() == ProjectConfigEntryType.ARRAY) {
            List<String> l =
                Arrays.asList(projectConfig.getPluginConfig(pluginName).getStringList(v.getKey()));
            oldValue = Joiner.on("\n").join(l);
            value = Joiner.on("\n").join(v.getValue().values);
          }
          if (Strings.emptyToNull(value) != null) {
            if (!value.equals(oldValue)) {
              validateProjectConfigEntryIsEditable(
                  projectConfigEntry, projectState, v.getKey(), pluginName);
              v.setValue(projectConfigEntry.preUpdate(v.getValue()));
              value = v.getValue().value;
              try {
                switch (projectConfigEntry.getType()) {
                  case BOOLEAN:
                    boolean newBooleanValue = Boolean.parseBoolean(value);
                    projectConfig.updatePluginConfig(
                        pluginName, cfg -> cfg.setBoolean(v.getKey(), newBooleanValue));
                    break;
                  case INT:
                    int newIntValue = Integer.parseInt(value);
                    projectConfig.updatePluginConfig(
                        pluginName, cfg -> cfg.setInt(v.getKey(), newIntValue));
                    break;
                  case LONG:
                    long newLongValue = Long.parseLong(value);
                    projectConfig.updatePluginConfig(
                        pluginName, cfg -> cfg.setLong(v.getKey(), newLongValue));
                    break;
                  case LIST:
                    if (!projectConfigEntry.getPermittedValues().contains(value)) {
                      throw new BadRequestException(
                          String.format(
                              "The value '%s' is not permitted for parameter '%s' of plugin '"
                                  + pluginName
                                  + "'",
                              value,
                              v.getKey()));
                    }
                    // $FALL-THROUGH$
                  case STRING:
                    String valueToSet = value;
                    projectConfig.updatePluginConfig(
                        pluginName, cfg -> cfg.setString(v.getKey(), valueToSet));
                    break;
                  case ARRAY:
                    projectConfig.updatePluginConfig(
                        pluginName, cfg -> cfg.setStringList(v.getKey(), v.getValue().values));
                    break;
                  default:
                    logger.atWarning().log(
                        "The type '%s' of parameter '%s' is not supported.",
                        projectConfigEntry.getType().name(), v.getKey());
                }
              } catch (NumberFormatException ex) {
                throw new BadRequestException(
                    String.format(
                        "The value '%s' of config parameter '%s' of plugin '%s' is invalid: %s",
                        v.getValue(), v.getKey(), pluginName, ex.getMessage()));
              }
            }
          } else {
            if (oldValue != null) {
              validateProjectConfigEntryIsEditable(
                  projectConfigEntry, projectState, v.getKey(), pluginName);
              projectConfig.updatePluginConfig(pluginName, cfg -> cfg.unset(v.getKey()));
            }
          }
        } else {
          throw new BadRequestException(
              String.format(
                  "The config parameter '%s' of plugin '%s' does not exist.",
                  v.getKey(), pluginName));
        }
      }
    }
  }

  private void updateCommentLinks(
      ProjectConfig projectConfig, Map<String, CommentLinkInput> input) {
    for (Map.Entry<String, CommentLinkInput> e : input.entrySet()) {
      String name = e.getKey();
      CommentLinkInput value = e.getValue();
      if (value != null) {
        // Add or update the commentlink section
        Config cfg = new Config();
        cfg.setString(COMMENTLINK, name, KEY_MATCH, value.match);
        cfg.setString(COMMENTLINK, name, KEY_LINK, value.link);
        cfg.setBoolean(COMMENTLINK, name, KEY_ENABLED, value.enabled == null || value.enabled);
        projectConfig.addCommentLinkSection(ProjectConfig.buildCommentLink(cfg, name, false));
      } else {
        // Delete the commentlink section
        projectConfig.removeCommentLinkSection(name);
      }
    }
  }

  private static void validateProjectConfigEntryIsEditable(
      ProjectConfigEntry projectConfigEntry,
      ProjectState projectState,
      String parameterName,
      String pluginName)
      throws BadRequestException {
    if (!projectConfigEntry.isEditable(projectState)) {
      throw new BadRequestException(
          String.format(
              "Not allowed to set parameter '%s' of plugin '%s' on project '%s'.",
              parameterName, pluginName, projectState.getName()));
    }
  }
}
