// Copyright (C) 2015 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.schema;

import static com.google.common.base.Preconditions.checkState;
import static com.google.gerrit.reviewdb.client.CoreDownloadSchemes.ANON_GIT;
import static com.google.gerrit.reviewdb.client.CoreDownloadSchemes.ANON_HTTP;
import static com.google.gerrit.reviewdb.client.CoreDownloadSchemes.HTTP;
import static com.google.gerrit.reviewdb.client.CoreDownloadSchemes.REPO_DOWNLOAD;
import static com.google.gerrit.reviewdb.client.CoreDownloadSchemes.SSH;
import static com.google.gerrit.server.config.ConfigUtil.storeSection;

import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo.DateFormat;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo.DiffView;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo.DownloadCommand;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo.EmailStrategy;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo.ReviewCategoryStrategy;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo.TimeFormat;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.UserConfigSections;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.gerrit.server.git.meta.VersionedMetaData.BatchMetaDataUpdate;
import com.google.gwtorm.jdbc.JdbcSchema;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevWalk;

public class Schema_119 extends SchemaVersion {
  private static final String CREATE_ACCOUNT_MSG = "Create Account";
  private static final ImmutableMap<String, String> LEGACY_DISPLAYNAME_MAP =
      ImmutableMap.<String, String>of(
          "ANON_GIT", ANON_GIT,
          "ANON_HTTP", ANON_HTTP,
          "HTTP", HTTP,
          "SSH", SSH,
          "REPO_DOWNLOAD", REPO_DOWNLOAD);

  private final GitRepositoryManager mgr;
  private final AllUsersName allUsersName;
  private final PersonIdent serverUser;

  @Inject
  Schema_119(
      Provider<Schema_118> prior,
      GitRepositoryManager mgr,
      AllUsersName allUsersName,
      @GerritPersonIdent PersonIdent serverUser) {
    super(prior);
    this.mgr = mgr;
    this.allUsersName = allUsersName;
    this.serverUser = serverUser;
  }

  @Override
  protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
    JdbcSchema schema = (JdbcSchema) db;
    Connection connection = schema.getConnection();
    String tableName = "accounts";
    String emailStrategy = "email_strategy";
    Set<String> columns = schema.getDialect().listColumns(connection, tableName);
    Map<Account.Id, GeneralPreferencesInfo> imports = new HashMap<>();
    HashMap<Account.Id, Timestamp> registeredOnByAccount = new HashMap<>();
    try (Statement stmt = ((JdbcSchema) db).getConnection().createStatement();
        ResultSet rs =
            stmt.executeQuery(
                "select "
                    + "account_id, "
                    + "maximum_page_size, "
                    + "show_site_header, "
                    + "use_flash_clipboard, "
                    + "download_url, "
                    + "download_command, "
                    + (columns.contains(emailStrategy)
                        ? emailStrategy + ", "
                        : "copy_self_on_email, ")
                    + "date_format, "
                    + "time_format, "
                    + "relative_date_in_change_table, "
                    + "diff_view, "
                    + "size_bar_in_change_table, "
                    + "legacycid_in_change_table, "
                    + "review_category_strategy, "
                    + "mute_common_path_prefixes, "
                    + "registered_on "
                    + "from "
                    + tableName)) {
      while (rs.next()) {
        GeneralPreferencesInfo p = new GeneralPreferencesInfo();
        Account.Id accountId = new Account.Id(rs.getInt(1));
        p.changesPerPage = (int) rs.getShort(2);
        p.showSiteHeader = toBoolean(rs.getString(3));
        p.useFlashClipboard = toBoolean(rs.getString(4));
        p.downloadScheme = convertToModernNames(rs.getString(5));
        p.downloadCommand = toDownloadCommand(rs.getString(6));
        p.emailStrategy = toEmailStrategy(rs.getString(7), columns.contains(emailStrategy));
        p.dateFormat = toDateFormat(rs.getString(8));
        p.timeFormat = toTimeFormat(rs.getString(9));
        p.relativeDateInChangeTable = toBoolean(rs.getString(10));
        p.diffView = toDiffView(rs.getString(11));
        p.sizeBarInChangeTable = toBoolean(rs.getString(12));
        p.legacycidInChangeTable = toBoolean(rs.getString(13));
        p.reviewCategoryStrategy = toReviewCategoryStrategy(rs.getString(14));
        p.muteCommonPathPrefixes = toBoolean(rs.getString(15));
        p.defaultBaseForMerges = GeneralPreferencesInfo.defaults().defaultBaseForMerges;
        imports.put(accountId, p);
        registeredOnByAccount.put(accountId, rs.getTimestamp(16));
      }
    }

    if (imports.isEmpty()) {
      return;
    }

    try (Repository git = mgr.openRepository(allUsersName);
        ObjectInserter inserter = getPackInserterFirst(git);
        ObjectReader reader = inserter.newReader();
        RevWalk rw = new RevWalk(reader)) {
      BatchRefUpdate bru = git.getRefDatabase().newBatchUpdate();
      ObjectId emptyTree = emptyTree(inserter);
      for (Map.Entry<Account.Id, GeneralPreferencesInfo> e : imports.entrySet()) {
        try (MetaDataUpdate md =
            new MetaDataUpdate(GitReferenceUpdated.DISABLED, allUsersName, git, bru)) {
          Account.Id accountId = e.getKey();
          VersionedAccountPreferences p = VersionedAccountPreferences.forUser(accountId);
          p.load(md);
          BatchMetaDataUpdate batch = p.openUpdate(md, inserter, reader, rw);
          if (p.getRevision() == null) {
            batch.write(
                buildCommit(
                    new PersonIdent(serverUser, registeredOnByAccount.get(accountId)),
                    emptyTree,
                    CREATE_ACCOUNT_MSG));
          }
          md.getCommitBuilder().setAuthor(serverUser);
          md.getCommitBuilder().setCommitter(serverUser);
          storeSection(
              p.getConfig(),
              UserConfigSections.GENERAL,
              null,
              e.getValue(),
              GeneralPreferencesInfo.defaults());
          batch.write(md.getCommitBuilder());
          batch.commit();
        }
      }

      inserter.flush();
      bru.execute(rw, NullProgressMonitor.INSTANCE);
    } catch (ConfigInvalidException | IOException ex) {
      throw new OrmException(ex);
    }
  }

  private String convertToModernNames(String s) {
    return !Strings.isNullOrEmpty(s) && LEGACY_DISPLAYNAME_MAP.containsKey(s)
        ? LEGACY_DISPLAYNAME_MAP.get(s)
        : s;
  }

  private static DownloadCommand toDownloadCommand(String v) {
    if (v == null) {
      return DownloadCommand.CHECKOUT;
    }
    return DownloadCommand.valueOf(v);
  }

  private static DateFormat toDateFormat(String v) {
    if (v == null) {
      return DateFormat.STD;
    }
    return DateFormat.valueOf(v);
  }

  private static TimeFormat toTimeFormat(String v) {
    if (v == null) {
      return TimeFormat.HHMM_12;
    }
    return TimeFormat.valueOf(v);
  }

  private static DiffView toDiffView(String v) {
    if (v == null) {
      return DiffView.SIDE_BY_SIDE;
    }
    return DiffView.valueOf(v);
  }

  private static EmailStrategy toEmailStrategy(String v, boolean emailStrategyColumnExists)
      throws OrmException {
    if (v == null) {
      return EmailStrategy.ENABLED;
    }
    if (emailStrategyColumnExists) {
      return EmailStrategy.valueOf(v);
    }
    if (v.equals("N")) {
      // EMAIL_STRATEGY='ENABLED' WHERE (COPY_SELF_ON_EMAIL='N')
      return EmailStrategy.ENABLED;
    } else if (v.equals("Y")) {
      // EMAIL_STRATEGY='CC_ON_OWN_COMMENTS' WHERE (COPY_SELF_ON_EMAIL='Y')
      return EmailStrategy.CC_ON_OWN_COMMENTS;
    } else {
      throw new OrmException("invalid value in accounts.copy_self_on_email: " + v);
    }
  }

  private static ReviewCategoryStrategy toReviewCategoryStrategy(String v) {
    if (v == null) {
      return ReviewCategoryStrategy.NONE;
    }
    return ReviewCategoryStrategy.valueOf(v);
  }

  private static boolean toBoolean(String v) {
    checkState(!Strings.isNullOrEmpty(v));
    return v.equals("Y");
  }
}
