// Copyright (C) 2020 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.config;

import com.google.gerrit.common.Nullable;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.client.DiffPreferencesInfo;
import com.google.gerrit.extensions.client.EditPreferencesInfo;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo;
import com.google.gerrit.proto.Entities.UserPreferences;
import com.google.gerrit.server.cache.proto.Cache.CachedPreferencesProto;
import com.google.gerrit.server.config.PreferencesParserUtil.DiffPreferencesParser;
import com.google.gerrit.server.config.PreferencesParserUtil.EditPreferencesParser;
import com.google.gerrit.server.config.PreferencesParserUtil.GeneralPreferencesParser;
import com.google.gerrit.server.config.PreferencesParserUtil.PreferencesParser;
import java.util.Optional;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;

/**
 * Container class for preferences serialized as Git-style config files. Keeps the values as {@link
 * CachedPreferencesProto}s as they are immutable and thread-safe.
 *
 * <p>The config string wrapped by this class might represent different structures. See {@link
 * CachedPreferencesProto} for more details.
 */
public record CachedPreferences(CachedPreferencesProto config) {
  public static final CachedPreferences EMPTY =
      fromCachedPreferencesProto(CachedPreferencesProto.getDefaultInstance());

  public Optional<CachedPreferencesProto> nonEmptyConfig() {
    return config().equals(EMPTY.config()) ? Optional.empty() : Optional.of(config());
  }

  /** Returns a cache-able representation of the preferences proto. */
  public static CachedPreferences fromUserPreferencesProto(UserPreferences proto) {
    return fromCachedPreferencesProto(
        CachedPreferencesProto.newBuilder().setUserPreferences(proto).build());
  }

  /** Returns a cache-able representation of the git config. */
  public static CachedPreferences fromLegacyConfig(Config cfg) {
    return fromCachedPreferencesProto(
        CachedPreferencesProto.newBuilder().setLegacyGitConfig(cfg.toText()).build());
  }

  /** Returns a cache-able representation of the preferences proto. */
  public static CachedPreferences fromCachedPreferencesProto(
      @Nullable CachedPreferencesProto proto) {
    if (proto != null) {
      return new CachedPreferences(proto);
    }
    return EMPTY;
  }

  public static GeneralPreferencesInfo general(
      Optional<CachedPreferences> defaultPreferences, CachedPreferences userPreferences) {
    return getPreferences(defaultPreferences, userPreferences, GeneralPreferencesParser.Instance);
  }

  public static DiffPreferencesInfo diff(
      Optional<CachedPreferences> defaultPreferences, CachedPreferences userPreferences) {
    return getPreferences(defaultPreferences, userPreferences, DiffPreferencesParser.Instance);
  }

  public static EditPreferencesInfo edit(
      Optional<CachedPreferences> defaultPreferences, CachedPreferences userPreferences) {
    return getPreferences(defaultPreferences, userPreferences, EditPreferencesParser.Instance);
  }

  public Config asConfig() {
    try {
      switch (config().getPreferencesCase()) {
        case LEGACY_GIT_CONFIG, PREFERENCES_NOT_SET -> {
          // continue below
          Config cfg = new Config();
          cfg.fromText(config().getLegacyGitConfig());
          return cfg;
        }
        case USER_PREFERENCES -> {}
      }
    } catch (ConfigInvalidException e) {
      throw new StorageException(e);
    }
    throw new StorageException(
        String.format(
            "Cannot parse the given config as a CachedPreferencesProto proto. Got [%s]", config()));
  }

  public UserPreferences asUserPreferencesProto() {
    if (config().hasUserPreferences()) {
      return config().getUserPreferences();
    }
    throw new StorageException(
        String.format(
            "Cannot parse the given config as a UserPreferences proto. Got [%s]", config()));
  }

  @Nullable
  private static Config configOrNull(Optional<CachedPreferences> cachedPreferences) {
    return cachedPreferences.map(CachedPreferences::asConfig).orElse(null);
  }

  private static <PreferencesT> PreferencesT getPreferences(
      Optional<CachedPreferences> defaultPreferences,
      CachedPreferences userPreferences,
      PreferencesParser<PreferencesT> preferencesParser) {
    try {
      CachedPreferencesProto userPreferencesProto = userPreferences.config();
      return switch (userPreferencesProto.getPreferencesCase()) {
        case USER_PREFERENCES ->
            preferencesParser.fromUserPreferences(
                userPreferencesProto.getUserPreferences(), configOrNull(defaultPreferences));
        case LEGACY_GIT_CONFIG ->
            preferencesParser.parse(
                userPreferences.asConfig(), configOrNull(defaultPreferences), null);
        case PREFERENCES_NOT_SET ->
            throw new ConfigInvalidException("Invalid config " + userPreferences);
      };
    } catch (ConfigInvalidException e) {
      return preferencesParser.getJavaDefaults();
    }
  }
}
