// 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 com.google.gerrit.common.errors.InvalidSshKeyException;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Account.FieldName;
import com.google.gerrit.reviewdb.client.AccountExternalId;
import com.google.gerrit.reviewdb.client.AccountSshKey;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.AccountException;
import com.google.gerrit.server.account.AccountManager;
import com.google.gerrit.server.account.AuthRequest;
import com.google.gerrit.server.account.Realm;
import com.google.gerrit.server.ssh.SshKeyCache;
import com.google.gerrit.sshd.BaseCommand;
import com.google.gerrit.sshd.CommandMetaData;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.ResultSet;
import com.google.inject.Inject;

import org.apache.sshd.server.Environment;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;

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;

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

  @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", multiValued = true, metaVar = "EMAIL", usage = "email addresses to add to the account")
  private List<String> addEmails = new ArrayList<String>();

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

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

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

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

  @Inject
  private IdentifiedUser currentUser;

  @Inject
  private ReviewDb db;

  @Inject
  private AccountManager manager;

  @Inject
  private SshKeyCache sshKeyCache;

  @Inject
  private AccountCache byIdCache;

  @Inject
  private Realm realm;

  @Override
  public void start(final Environment env) {
    startThread(new CommandRunnable() {
      @Override
      public void run() throws Exception {
        if (!currentUser.getCapabilities().canAdministrateServer()) {
          String msg =
              String.format(
                  "fatal: %s does not have \"Administrator\" capability.",
                  currentUser.getUserName());
          throw new UnloggedFailure(1, msg);
        }
        parseCommandLine();
        validate();
        setAccount();
      }
    });
  }

  private void validate() throws UnloggedFailure {
    if (active && inactive) {
      throw new UnloggedFailure(1,
          "--active and --inactive options are mutually exclusive.");
    }
    if (addSshKeys.contains("-") && deleteSshKeys.contains("-")) {
      throw new UnloggedFailure(1, "Only one option may use the stdin");
    }
    if (deleteSshKeys.contains("ALL")) {
      deleteSshKeys = Collections.singletonList("ALL");
    }
    if (deleteEmails.contains("ALL")) {
      deleteEmails = Collections.singletonList("ALL");
    }
  }

  private void setAccount() throws OrmException, IOException, UnloggedFailure {

    final Account account = db.accounts().get(id);
    boolean accountUpdated = false;
    boolean sshKeysUpdated = false;

    ResultSet<AccountExternalId> ids = db.accountExternalIds().byAccount(id);
    for (AccountExternalId extId : ids) {
      if (extId.isScheme(AccountExternalId.SCHEME_USERNAME)) {
        account.setUserName(extId.getSchemeRest());
      }
    }

    for (String email : addEmails) {
      link(id, email);
    }

    for (String email : deleteEmails) {
      deleteMail(id, email);
    }

    if (fullName != null) {
      if (realm.allowsEdit(FieldName.FULL_NAME)) {
        account.setFullName(fullName);
        accountUpdated = true;
      } else {
        throw new UnloggedFailure(1, "The realm doesn't allow editing names");
      }
    }

    if (httpPassword != null) {
      setHttpPassword(id, httpPassword);
    }

    if (active) {
      accountUpdated = true;
      account.setActive(true);
    } else if (inactive) {
      accountUpdated = true;
      account.setActive(false);
    }

    addSshKeys = readSshKey(addSshKeys);
    if (!addSshKeys.isEmpty()) {
      sshKeysUpdated = true;
      addSshKeys(addSshKeys, account);
    }

    deleteSshKeys = readSshKey(deleteSshKeys);
    if (!deleteSshKeys.isEmpty()) {
      sshKeysUpdated = true;
      deleteSshKeys(deleteSshKeys, account);
    }

    if (accountUpdated) {
      db.accounts().update(Collections.singleton(account));
      byIdCache.evict(id);
    }

    if (sshKeysUpdated) {
      sshKeyCache.evict(account.getUserName());
    }
  }

  private void addSshKeys(final List<String> keys, final Account account)
      throws OrmException, UnloggedFailure {
    List<AccountSshKey> accountKeys = new ArrayList<AccountSshKey>();
    int seq = db.accountSshKeys().byAccount(account.getId()).toList().size();
    for (String key : keys) {
      try {
        seq++;
        AccountSshKey accountSshKey = sshKeyCache.create(
            new AccountSshKey.Id(account.getId(), seq), key.trim());
        accountKeys.add(accountSshKey);
      } catch (InvalidSshKeyException e) {
        throw new UnloggedFailure(1, "fatal: invalid ssh key");
      }
    }
    db.accountSshKeys().insert(accountKeys);
  }

  private void deleteSshKeys(final List<String> keys, final Account account)
      throws OrmException {
    ResultSet<AccountSshKey> allKeys = db.accountSshKeys().byAccount(account.getId());
    if (keys.contains("ALL")) {
      db.accountSshKeys().delete(allKeys);
    } else {
      List<AccountSshKey> accountKeys = new ArrayList<AccountSshKey>();
      for (String key : keys) {
        for (AccountSshKey accountSshKey : allKeys) {
          if (key.trim().equals(accountSshKey.getSshPublicKey())
              || accountSshKey.getComment().trim().equals(key)) {
            accountKeys.add(accountSshKey);
          }
        }
      }
      db.accountSshKeys().delete(accountKeys);
    }
  }

  private void deleteMail(Account.Id id, final String mailAddress)
      throws UnloggedFailure, OrmException {
    if (mailAddress.equals("ALL")) {
      ResultSet<AccountExternalId> ids = db.accountExternalIds().byAccount(id);
      for (AccountExternalId extId : ids) {
        if (extId.isScheme(AccountExternalId.SCHEME_MAILTO)) {
          unlink(id, extId.getEmailAddress());
        }
      }
    } else {
      AccountExternalId.Key key = new AccountExternalId.Key(
          AccountExternalId.SCHEME_MAILTO, mailAddress);
      AccountExternalId extId = db.accountExternalIds().get(key);
      if (extId != null) {
        unlink(id, mailAddress);
      }
    }
  }

  private void setHttpPassword(Account.Id id, final String httpPassword)
      throws UnloggedFailure, OrmException {
    ResultSet<AccountExternalId> ids = db.accountExternalIds().byAccount(id);
    for (AccountExternalId extId: ids) {
      if (extId.isScheme(AccountExternalId.SCHEME_USERNAME)) {
        extId.setPassword(httpPassword);
        db.accountExternalIds().update(Collections.singleton(extId));
        byIdCache.evict(id);
      }
    }
  }

  private void unlink(Account.Id id, final String mailAddress)
      throws UnloggedFailure {
    try {
      manager.unlink(id, AuthRequest.forEmail(mailAddress));
    } catch (AccountException ex) {
      throw die(ex.getMessage());
    }
  }

  private void link(Account.Id id, final String mailAddress)
      throws UnloggedFailure {
    try {
      manager.link(id, AuthRequest.forEmail(mailAddress));
    } catch (AccountException ex) {
      throw die(ex.getMessage());
    }
  }

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