// Copyright (C) 2012 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.sshd.commands;

import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.base.Strings;
import com.google.gerrit.common.RawInputUtil;
import com.google.gerrit.common.errors.EmailException;
import com.google.gerrit.extensions.api.accounts.EmailInput;
import com.google.gerrit.extensions.common.EmailInfo;
import com.google.gerrit.extensions.common.SshKeyInfo;
import com.google.gerrit.extensions.restapi.AuthException;
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.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountSshKey;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountResource;
import com.google.gerrit.server.account.AddSshKey;
import com.google.gerrit.server.account.CreateEmail;
import com.google.gerrit.server.account.DeleteActive;
import com.google.gerrit.server.account.DeleteEmail;
import com.google.gerrit.server.account.DeleteSshKey;
import com.google.gerrit.server.account.GetEmails;
import com.google.gerrit.server.account.GetSshKeys;
import com.google.gerrit.server.account.PutActive;
import com.google.gerrit.server.account.PutHttpPassword;
import com.google.gerrit.server.account.PutName;
import com.google.gerrit.server.account.PutPreferred;
import com.google.gerrit.server.permissions.GlobalPermission;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.sshd.CommandMetaData;
import com.google.gerrit.sshd.SshCommand;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;

/** Set a user's account settings. * */
@CommandMetaData(name = "set-account", description = "Change an account's settings")
final class SetAccountCommand extends SshCommand {

  @Argument(
      index = 0,
      required = true,
      metaVar = "USER",
      usage = "full name, email-address, ssh username or account id")
  private Account.Id id;

  @Option(name = "--full-name", metaVar = "NAME", usage = "display name of the account")
  private String fullName;

  @Option(name = "--active", usage = "set account's state to active")
  private boolean active;

  @Option(name = "--inactive", usage = "set account's state to inactive")
  private boolean inactive;

  @Option(name = "--add-email", metaVar = "EMAIL", usage = "email addresses to add to the account")
  private List<String> addEmails = new ArrayList<>();

  @Option(
      name = "--delete-email",
      metaVar = "EMAIL",
      usage = "email addresses to delete from the account")
  private List<String> deleteEmails = new ArrayList<>();

  @Option(
      name = "--preferred-email",
      metaVar = "EMAIL",
      usage = "a registered email address from the account")
  private String preferredEmail;

  @Option(name = "--add-ssh-key", metaVar = "-|KEY", usage = "public keys to add to the account")
  private List<String> addSshKeys = new ArrayList<>();

  @Option(
      name = "--delete-ssh-key",
      metaVar = "-|KEY",
      usage = "public keys to delete from the account")
  private List<String> deleteSshKeys = new ArrayList<>();

  @Option(
      name = "--http-password",
      metaVar = "PASSWORD",
      usage = "password for HTTP authentication for the account")
  private String httpPassword;

  @Option(name = "--clear-http-password", usage = "clear HTTP password for the account")
  private boolean clearHttpPassword;

  @Option(name = "--generate-http-password", usage = "generate a new HTTP password for the account")
  private boolean generateHttpPassword;

  @Inject private IdentifiedUser.GenericFactory genericUserFactory;

  @Inject private CreateEmail.Factory createEmailFactory;

  @Inject private GetEmails getEmails;

  @Inject private DeleteEmail deleteEmail;

  @Inject private PutPreferred putPreferred;

  @Inject private PutName putName;

  @Inject private PutHttpPassword putHttpPassword;

  @Inject private PutActive putActive;

  @Inject private DeleteActive deleteActive;

  @Inject private AddSshKey addSshKey;

  @Inject private GetSshKeys getSshKeys;

  @Inject private DeleteSshKey deleteSshKey;

  @Inject private PermissionBackend permissionBackend;

  @Inject private Provider<CurrentUser> userProvider;

  private IdentifiedUser user;
  private AccountResource rsrc;

  @Override
  public void run() throws Exception {
    user = genericUserFactory.create(id);

    validate();
    setAccount();
  }

  private void validate() throws UnloggedFailure {
    PermissionBackend.WithUser userPermission = permissionBackend.user(userProvider);

    boolean isAdmin = userPermission.testOrFalse(GlobalPermission.ADMINISTRATE_SERVER);
    boolean canModifyAccount =
        isAdmin || userPermission.testOrFalse(GlobalPermission.MODIFY_ACCOUNT);

    if (!user.hasSameAccountId(userProvider.get()) && !canModifyAccount) {
      throw die(
          "Setting another user's account information requries 'modify account' or 'administrate server' capabilities.");
    }
    if (active || inactive) {
      if (!canModifyAccount) {
        throw die(
            "--active and --inactive require 'modify account' or 'administrate server' capabilities.");
      }
      if (active && inactive) {
        throw die("--active and --inactive options are mutually exclusive.");
      }
    }

    if (generateHttpPassword && clearHttpPassword) {
      throw die("--generate-http-password and --clear-http-password are mutually exclusive.");
    }
    if (!Strings.isNullOrEmpty(httpPassword)) { // gave --http-password
      if (!isAdmin) {
        throw die("--http-password requires 'administrate server' capabilities.");
      }
      if (generateHttpPassword) {
        throw die("--http-password and --generate-http-password options are mutually exclusive.");
      }
      if (clearHttpPassword) {
        throw die("--http-password and --clear-http-password options are mutually exclusive.");
      }
    }
    if (addSshKeys.contains("-") && deleteSshKeys.contains("-")) {
      throw die("Only one option may use the stdin");
    }
    if (deleteSshKeys.contains("ALL")) {
      deleteSshKeys = Collections.singletonList("ALL");
    }
    if (deleteEmails.contains("ALL")) {
      deleteEmails = Collections.singletonList("ALL");
    }
    if (deleteEmails.contains(preferredEmail)) {
      throw die(
          "--preferred-email and --delete-email options are mutually "
              + "exclusive for the same email address.");
    }
  }

  private void setAccount()
      throws OrmException, IOException, UnloggedFailure, ConfigInvalidException,
          PermissionBackendException {
    rsrc = new AccountResource(user);
    try {
      for (String email : addEmails) {
        addEmail(email);
      }

      for (String email : deleteEmails) {
        deleteEmail(email);
      }

      if (preferredEmail != null) {
        putPreferred(preferredEmail);
      }

      if (fullName != null) {
        PutName.Input in = new PutName.Input();
        in.name = fullName;
        putName.apply(rsrc, in);
      }

      if (httpPassword != null || clearHttpPassword || generateHttpPassword) {
        PutHttpPassword.Input in = new PutHttpPassword.Input();
        in.httpPassword = httpPassword;
        if (generateHttpPassword) {
          in.generate = true;
        }
        Response<String> resp = putHttpPassword.apply(rsrc, in);
        if (generateHttpPassword) {
          stdout.print("New password: " + resp.value() + "\n");
        }
      }

      if (active) {
        putActive.apply(rsrc, null);
      } else if (inactive) {
        try {
          deleteActive.apply(rsrc, null);
        } catch (ResourceNotFoundException e) {
          // user is already inactive
        }
      }

      addSshKeys = readSshKey(addSshKeys);
      if (!addSshKeys.isEmpty()) {
        addSshKeys(addSshKeys);
      }

      deleteSshKeys = readSshKey(deleteSshKeys);
      if (!deleteSshKeys.isEmpty()) {
        deleteSshKeys(deleteSshKeys);
      }
    } catch (RestApiException e) {
      throw die(e.getMessage());
    }
  }

  private void addSshKeys(List<String> sshKeys)
      throws RestApiException, OrmException, IOException, ConfigInvalidException,
          PermissionBackendException {
    for (String sshKey : sshKeys) {
      AddSshKey.Input in = new AddSshKey.Input();
      in.raw = RawInputUtil.create(sshKey.getBytes(UTF_8), "plain/text");
      addSshKey.apply(rsrc, in);
    }
  }

  private void deleteSshKeys(List<String> sshKeys)
      throws RestApiException, OrmException, RepositoryNotFoundException, IOException,
          ConfigInvalidException, PermissionBackendException {
    List<SshKeyInfo> infos = getSshKeys.apply(rsrc);
    if (sshKeys.contains("ALL")) {
      for (SshKeyInfo i : infos) {
        deleteSshKey(i);
      }
    } else {
      for (String sshKey : sshKeys) {
        for (SshKeyInfo i : infos) {
          if (sshKey.trim().equals(i.sshPublicKey) || sshKey.trim().equals(i.comment)) {
            deleteSshKey(i);
          }
        }
      }
    }
  }

  private void deleteSshKey(SshKeyInfo i)
      throws AuthException, OrmException, RepositoryNotFoundException, IOException,
          ConfigInvalidException, PermissionBackendException {
    AccountSshKey sshKey =
        new AccountSshKey(new AccountSshKey.Id(user.getAccountId(), i.seq), i.sshPublicKey);
    deleteSshKey.apply(new AccountResource.SshKey(user, sshKey), null);
  }

  private void addEmail(String email)
      throws UnloggedFailure, RestApiException, OrmException, IOException, ConfigInvalidException,
          PermissionBackendException {
    EmailInput in = new EmailInput();
    in.email = email;
    in.noConfirmation = true;
    try {
      createEmailFactory.create(email).apply(rsrc, in);
    } catch (EmailException e) {
      throw die(e.getMessage());
    }
  }

  private void deleteEmail(String email)
      throws RestApiException, OrmException, IOException, ConfigInvalidException,
          PermissionBackendException {
    if (email.equals("ALL")) {
      List<EmailInfo> emails = getEmails.apply(rsrc);
      for (EmailInfo e : emails) {
        deleteEmail.apply(new AccountResource.Email(user, e.email), new DeleteEmail.Input());
      }
    } else {
      deleteEmail.apply(new AccountResource.Email(user, email), new DeleteEmail.Input());
    }
  }

  private void putPreferred(String email)
      throws RestApiException, OrmException, IOException, PermissionBackendException,
          ConfigInvalidException {
    for (EmailInfo e : getEmails.apply(rsrc)) {
      if (e.email.equals(email)) {
        putPreferred.apply(new AccountResource.Email(user, email), null);
        return;
      }
    }
    stderr.println("preferred email not found: " + email);
  }

  private List<String> readSshKey(List<String> sshKeys)
      throws UnsupportedEncodingException, IOException {
    if (!sshKeys.isEmpty()) {
      int idx = sshKeys.indexOf("-");
      if (idx >= 0) {
        StringBuilder sshKey = new StringBuilder();
        BufferedReader br = new BufferedReader(new InputStreamReader(in, UTF_8));
        String line;
        while ((line = br.readLine()) != null) {
          sshKey.append(line).append("\n");
        }
        sshKeys.set(idx, sshKey.toString());
      }
    }
    return sshKeys;
  }
}
