// Copyright (C) 2018 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.account;

import static com.google.common.base.Preconditions.checkState;
import static com.google.gerrit.server.config.ConfigUtil.loadSection;
import static com.google.gerrit.server.config.ConfigUtil.skipField;
import static com.google.gerrit.server.config.ConfigUtil.storeSection;
import static com.google.gerrit.server.git.UserConfigSections.CHANGE_TABLE;
import static com.google.gerrit.server.git.UserConfigSections.CHANGE_TABLE_COLUMN;
import static com.google.gerrit.server.git.UserConfigSections.KEY_ID;
import static com.google.gerrit.server.git.UserConfigSections.KEY_TARGET;
import static com.google.gerrit.server.git.UserConfigSections.KEY_URL;
import static java.util.Objects.requireNonNull;

import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
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.extensions.client.MenuItem;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.git.UserConfigSections;
import com.google.gerrit.server.git.ValidationError;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.gerrit.server.git.meta.VersionedMetaData;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Repository;

/**
 * Parses/writes preferences from/to a {@link Config} file.
 *
 * <p>This is a low-level API. Read/write of preferences in a user branch should be done through
 * {@link AccountsUpdate} or {@link AccountConfig}.
 *
 * <p>The config file has separate sections for general, diff and edit preferences:
 *
 * <pre>
 *   [general]
 *     showSiteHeader = false
 *   [diff]
 *     hideTopMenu = true
 *   [edit]
 *     lineLength = 80
 * </pre>
 *
 * <p>The parameter names match the names that are used in the preferences REST API.
 *
 * <p>If the preference is omitted in the config file, then the default value for the preference is
 * used.
 *
 * <p>Defaults for preferences that apply for all accounts can be configured in the {@code
 * refs/users/default} branch in the {@code All-Users} repository. The config for the default
 * preferences must be provided to this class so that it can read default values from it.
 *
 * <p>The preferences are lazily parsed.
 */
public class Preferences {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  public static final String PREFERENCES_CONFIG = "preferences.config";

  private final Account.Id accountId;
  private final Config cfg;
  private final Config defaultCfg;
  private final ValidationError.Sink validationErrorSink;

  private GeneralPreferencesInfo generalPreferences;
  private DiffPreferencesInfo diffPreferences;
  private EditPreferencesInfo editPreferences;

  Preferences(
      Account.Id accountId,
      Config cfg,
      Config defaultCfg,
      ValidationError.Sink validationErrorSink) {
    this.accountId = requireNonNull(accountId, "accountId");
    this.cfg = requireNonNull(cfg, "cfg");
    this.defaultCfg = requireNonNull(defaultCfg, "defaultCfg");
    this.validationErrorSink = requireNonNull(validationErrorSink, "validationErrorSink");
  }

  public GeneralPreferencesInfo getGeneralPreferences() {
    if (generalPreferences == null) {
      parse();
    }
    return generalPreferences;
  }

  public DiffPreferencesInfo getDiffPreferences() {
    if (diffPreferences == null) {
      parse();
    }
    return diffPreferences;
  }

  public EditPreferencesInfo getEditPreferences() {
    if (editPreferences == null) {
      parse();
    }
    return editPreferences;
  }

  public void parse() {
    generalPreferences = parseGeneralPreferences(null);
    diffPreferences = parseDiffPreferences(null);
    editPreferences = parseEditPreferences(null);
  }

  public Config saveGeneralPreferences(
      Optional<GeneralPreferencesInfo> generalPreferencesInput,
      Optional<DiffPreferencesInfo> diffPreferencesInput,
      Optional<EditPreferencesInfo> editPreferencesInput)
      throws ConfigInvalidException {
    if (generalPreferencesInput.isPresent()) {
      GeneralPreferencesInfo mergedGeneralPreferencesInput =
          parseGeneralPreferences(generalPreferencesInput.get());

      storeSection(
          cfg,
          UserConfigSections.GENERAL,
          null,
          mergedGeneralPreferencesInput,
          parseDefaultGeneralPreferences(defaultCfg, null));
      setChangeTable(cfg, mergedGeneralPreferencesInput.changeTable);
      setMy(cfg, mergedGeneralPreferencesInput.my);

      // evict the cached general preferences
      this.generalPreferences = null;
    }

    if (diffPreferencesInput.isPresent()) {
      DiffPreferencesInfo mergedDiffPreferencesInput =
          parseDiffPreferences(diffPreferencesInput.get());

      storeSection(
          cfg,
          UserConfigSections.DIFF,
          null,
          mergedDiffPreferencesInput,
          parseDefaultDiffPreferences(defaultCfg, null));

      // evict the cached diff preferences
      this.diffPreferences = null;
    }

    if (editPreferencesInput.isPresent()) {
      EditPreferencesInfo mergedEditPreferencesInput =
          parseEditPreferences(editPreferencesInput.get());

      storeSection(
          cfg,
          UserConfigSections.EDIT,
          null,
          mergedEditPreferencesInput,
          parseDefaultEditPreferences(defaultCfg, null));

      // evict the cached edit preferences
      this.editPreferences = null;
    }

    return cfg;
  }

  private GeneralPreferencesInfo parseGeneralPreferences(@Nullable GeneralPreferencesInfo input) {
    try {
      return parseGeneralPreferences(cfg, defaultCfg, input);
    } catch (ConfigInvalidException e) {
      validationErrorSink.error(
          new ValidationError(
              PREFERENCES_CONFIG,
              String.format(
                  "Invalid general preferences for account %d: %s",
                  accountId.get(), e.getMessage())));
      return new GeneralPreferencesInfo();
    }
  }

  private DiffPreferencesInfo parseDiffPreferences(@Nullable DiffPreferencesInfo input) {
    try {
      return parseDiffPreferences(cfg, defaultCfg, input);
    } catch (ConfigInvalidException e) {
      validationErrorSink.error(
          new ValidationError(
              PREFERENCES_CONFIG,
              String.format(
                  "Invalid diff preferences for account %d: %s", accountId.get(), e.getMessage())));
      return new DiffPreferencesInfo();
    }
  }

  private EditPreferencesInfo parseEditPreferences(@Nullable EditPreferencesInfo input) {
    try {
      return parseEditPreferences(cfg, defaultCfg, input);
    } catch (ConfigInvalidException e) {
      validationErrorSink.error(
          new ValidationError(
              PREFERENCES_CONFIG,
              String.format(
                  "Invalid edit preferences for account %d: %s", accountId.get(), e.getMessage())));
      return new EditPreferencesInfo();
    }
  }

  private static GeneralPreferencesInfo parseGeneralPreferences(
      Config cfg, @Nullable Config defaultCfg, @Nullable GeneralPreferencesInfo input)
      throws ConfigInvalidException {
    GeneralPreferencesInfo r =
        loadSection(
            cfg,
            UserConfigSections.GENERAL,
            null,
            new GeneralPreferencesInfo(),
            defaultCfg != null
                ? parseDefaultGeneralPreferences(defaultCfg, input)
                : GeneralPreferencesInfo.defaults(),
            input);
    if (input != null) {
      r.changeTable = input.changeTable;
      r.my = input.my;
    } else {
      r.changeTable = parseChangeTableColumns(cfg, defaultCfg);
      r.my = parseMyMenus(cfg, defaultCfg);
    }
    return r;
  }

  private static DiffPreferencesInfo parseDiffPreferences(
      Config cfg, @Nullable Config defaultCfg, @Nullable DiffPreferencesInfo input)
      throws ConfigInvalidException {
    return loadSection(
        cfg,
        UserConfigSections.DIFF,
        null,
        new DiffPreferencesInfo(),
        defaultCfg != null
            ? parseDefaultDiffPreferences(defaultCfg, input)
            : DiffPreferencesInfo.defaults(),
        input);
  }

  private static EditPreferencesInfo parseEditPreferences(
      Config cfg, @Nullable Config defaultCfg, @Nullable EditPreferencesInfo input)
      throws ConfigInvalidException {
    return loadSection(
        cfg,
        UserConfigSections.EDIT,
        null,
        new EditPreferencesInfo(),
        defaultCfg != null
            ? parseDefaultEditPreferences(defaultCfg, input)
            : EditPreferencesInfo.defaults(),
        input);
  }

  private static GeneralPreferencesInfo parseDefaultGeneralPreferences(
      Config defaultCfg, GeneralPreferencesInfo input) throws ConfigInvalidException {
    GeneralPreferencesInfo allUserPrefs = new GeneralPreferencesInfo();
    loadSection(
        defaultCfg,
        UserConfigSections.GENERAL,
        null,
        allUserPrefs,
        GeneralPreferencesInfo.defaults(),
        input);
    return updateGeneralPreferencesDefaults(allUserPrefs);
  }

  private static DiffPreferencesInfo parseDefaultDiffPreferences(
      Config defaultCfg, DiffPreferencesInfo input) throws ConfigInvalidException {
    DiffPreferencesInfo allUserPrefs = new DiffPreferencesInfo();
    loadSection(
        defaultCfg,
        UserConfigSections.DIFF,
        null,
        allUserPrefs,
        DiffPreferencesInfo.defaults(),
        input);
    return updateDiffPreferencesDefaults(allUserPrefs);
  }

  private static EditPreferencesInfo parseDefaultEditPreferences(
      Config defaultCfg, EditPreferencesInfo input) throws ConfigInvalidException {
    EditPreferencesInfo allUserPrefs = new EditPreferencesInfo();
    loadSection(
        defaultCfg,
        UserConfigSections.EDIT,
        null,
        allUserPrefs,
        EditPreferencesInfo.defaults(),
        input);
    return updateEditPreferencesDefaults(allUserPrefs);
  }

  private static GeneralPreferencesInfo updateGeneralPreferencesDefaults(
      GeneralPreferencesInfo input) {
    GeneralPreferencesInfo result = GeneralPreferencesInfo.defaults();
    try {
      for (Field field : input.getClass().getDeclaredFields()) {
        if (skipField(field)) {
          continue;
        }
        Object newVal = field.get(input);
        if (newVal != null) {
          field.set(result, newVal);
        }
      }
    } catch (IllegalAccessException e) {
      logger.atSevere().withCause(e).log("Failed to apply default general preferences");
      return GeneralPreferencesInfo.defaults();
    }
    return result;
  }

  private static DiffPreferencesInfo updateDiffPreferencesDefaults(DiffPreferencesInfo input) {
    DiffPreferencesInfo result = DiffPreferencesInfo.defaults();
    try {
      for (Field field : input.getClass().getDeclaredFields()) {
        if (skipField(field)) {
          continue;
        }
        Object newVal = field.get(input);
        if (newVal != null) {
          field.set(result, newVal);
        }
      }
    } catch (IllegalAccessException e) {
      logger.atSevere().withCause(e).log("Failed to apply default diff preferences");
      return DiffPreferencesInfo.defaults();
    }
    return result;
  }

  private static EditPreferencesInfo updateEditPreferencesDefaults(EditPreferencesInfo input) {
    EditPreferencesInfo result = EditPreferencesInfo.defaults();
    try {
      for (Field field : input.getClass().getDeclaredFields()) {
        if (skipField(field)) {
          continue;
        }
        Object newVal = field.get(input);
        if (newVal != null) {
          field.set(result, newVal);
        }
      }
    } catch (IllegalAccessException e) {
      logger.atSevere().withCause(e).log("Failed to apply default edit preferences");
      return EditPreferencesInfo.defaults();
    }
    return result;
  }

  private static List<String> parseChangeTableColumns(Config cfg, @Nullable Config defaultCfg) {
    List<String> changeTable = changeTable(cfg);
    if (changeTable == null && defaultCfg != null) {
      changeTable = changeTable(defaultCfg);
    }
    return changeTable;
  }

  private static List<MenuItem> parseMyMenus(Config cfg, @Nullable Config defaultCfg) {
    List<MenuItem> my = my(cfg);
    if (my.isEmpty() && defaultCfg != null) {
      my = my(defaultCfg);
    }
    if (my.isEmpty()) {
      my.add(new MenuItem("Changes", "#/dashboard/self", null));
      my.add(new MenuItem("Draft Comments", "#/q/has:draft", null));
      my.add(new MenuItem("Edits", "#/q/has:edit", null));
      my.add(new MenuItem("Watched Changes", "#/q/is:watched+is:open", null));
      my.add(new MenuItem("Starred Changes", "#/q/is:starred", null));
      my.add(new MenuItem("Groups", "#/groups/self", null));
    }
    return my;
  }

  public static GeneralPreferencesInfo readDefaultGeneralPreferences(
      AllUsersName allUsersName, Repository allUsersRepo)
      throws IOException, ConfigInvalidException {
    return parseGeneralPreferences(readDefaultConfig(allUsersName, allUsersRepo), null, null);
  }

  public static DiffPreferencesInfo readDefaultDiffPreferences(
      AllUsersName allUsersName, Repository allUsersRepo)
      throws IOException, ConfigInvalidException {
    return parseDiffPreferences(readDefaultConfig(allUsersName, allUsersRepo), null, null);
  }

  public static EditPreferencesInfo readDefaultEditPreferences(
      AllUsersName allUsersName, Repository allUsersRepo)
      throws IOException, ConfigInvalidException {
    return parseEditPreferences(readDefaultConfig(allUsersName, allUsersRepo), null, null);
  }

  static Config readDefaultConfig(AllUsersName allUsersName, Repository allUsersRepo)
      throws IOException, ConfigInvalidException {
    VersionedDefaultPreferences defaultPrefs = new VersionedDefaultPreferences();
    defaultPrefs.load(allUsersName, allUsersRepo);
    return defaultPrefs.getConfig();
  }

  public static GeneralPreferencesInfo updateDefaultGeneralPreferences(
      MetaDataUpdate md, GeneralPreferencesInfo input) throws IOException, ConfigInvalidException {
    VersionedDefaultPreferences defaultPrefs = new VersionedDefaultPreferences();
    defaultPrefs.load(md);
    storeSection(
        defaultPrefs.getConfig(),
        UserConfigSections.GENERAL,
        null,
        input,
        GeneralPreferencesInfo.defaults());
    setMy(defaultPrefs.getConfig(), input.my);
    setChangeTable(defaultPrefs.getConfig(), input.changeTable);
    defaultPrefs.commit(md);

    return parseGeneralPreferences(defaultPrefs.getConfig(), null, null);
  }

  public static DiffPreferencesInfo updateDefaultDiffPreferences(
      MetaDataUpdate md, DiffPreferencesInfo input) throws IOException, ConfigInvalidException {
    VersionedDefaultPreferences defaultPrefs = new VersionedDefaultPreferences();
    defaultPrefs.load(md);
    storeSection(
        defaultPrefs.getConfig(),
        UserConfigSections.DIFF,
        null,
        input,
        DiffPreferencesInfo.defaults());
    defaultPrefs.commit(md);

    return parseDiffPreferences(defaultPrefs.getConfig(), null, null);
  }

  public static EditPreferencesInfo updateDefaultEditPreferences(
      MetaDataUpdate md, EditPreferencesInfo input) throws IOException, ConfigInvalidException {
    VersionedDefaultPreferences defaultPrefs = new VersionedDefaultPreferences();
    defaultPrefs.load(md);
    storeSection(
        defaultPrefs.getConfig(),
        UserConfigSections.EDIT,
        null,
        input,
        EditPreferencesInfo.defaults());
    defaultPrefs.commit(md);

    return parseEditPreferences(defaultPrefs.getConfig(), null, null);
  }

  private static List<String> changeTable(Config cfg) {
    return Lists.newArrayList(cfg.getStringList(CHANGE_TABLE, null, CHANGE_TABLE_COLUMN));
  }

  private static void setChangeTable(Config cfg, List<String> changeTable) {
    if (changeTable != null) {
      unsetSection(cfg, UserConfigSections.CHANGE_TABLE);
      cfg.setStringList(UserConfigSections.CHANGE_TABLE, null, CHANGE_TABLE_COLUMN, changeTable);
    }
  }

  private static List<MenuItem> my(Config cfg) {
    List<MenuItem> my = new ArrayList<>();
    for (String subsection : cfg.getSubsections(UserConfigSections.MY)) {
      String url = my(cfg, subsection, KEY_URL, "#/");
      String target = my(cfg, subsection, KEY_TARGET, url.startsWith("#") ? null : "_blank");
      my.add(new MenuItem(subsection, url, target, my(cfg, subsection, KEY_ID, null)));
    }
    return my;
  }

  private static String my(Config cfg, String subsection, String key, String defaultValue) {
    String val = cfg.getString(UserConfigSections.MY, subsection, key);
    return !Strings.isNullOrEmpty(val) ? val : defaultValue;
  }

  private static void setMy(Config cfg, List<MenuItem> my) {
    if (my != null) {
      unsetSection(cfg, UserConfigSections.MY);
      for (MenuItem item : my) {
        checkState(!isNullOrEmpty(item.name), "MenuItem.name must not be null or empty");
        checkState(!isNullOrEmpty(item.url), "MenuItem.url must not be null or empty");

        setMy(cfg, item.name, KEY_URL, item.url);
        setMy(cfg, item.name, KEY_TARGET, item.target);
        setMy(cfg, item.name, KEY_ID, item.id);
      }
    }
  }

  public static void validateMy(List<MenuItem> my) throws BadRequestException {
    if (my == null) {
      return;
    }
    for (MenuItem item : my) {
      checkRequiredMenuItemField(item.name, "name");
      checkRequiredMenuItemField(item.url, "URL");
    }
  }

  private static void checkRequiredMenuItemField(String value, String name)
      throws BadRequestException {
    if (isNullOrEmpty(value)) {
      throw new BadRequestException(name + " for menu item is required");
    }
  }

  private static boolean isNullOrEmpty(String value) {
    return value == null || value.trim().isEmpty();
  }

  private static void setMy(Config cfg, String section, String key, @Nullable String val) {
    if (val == null || val.trim().isEmpty()) {
      cfg.unset(UserConfigSections.MY, section.trim(), key);
    } else {
      cfg.setString(UserConfigSections.MY, section.trim(), key, val.trim());
    }
  }

  private static void unsetSection(Config cfg, String section) {
    cfg.unsetSection(section, null);
    for (String subsection : cfg.getSubsections(section)) {
      cfg.unsetSection(section, subsection);
    }
  }

  private static class VersionedDefaultPreferences extends VersionedMetaData {
    private Config cfg;

    @Override
    protected String getRefName() {
      return RefNames.REFS_USERS_DEFAULT;
    }

    private Config getConfig() {
      checkState(cfg != null, "Default preferences not loaded yet.");
      return cfg;
    }

    @Override
    protected void onLoad() throws IOException, ConfigInvalidException {
      cfg = readConfig(PREFERENCES_CONFIG);
    }

    @Override
    protected boolean onSave(CommitBuilder commit) throws IOException, ConfigInvalidException {
      if (Strings.isNullOrEmpty(commit.getMessage())) {
        commit.setMessage("Update default preferences\n");
      }
      saveConfig(PREFERENCES_CONFIG, cfg);
      return true;
    }
  }
}
