// 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.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. **/
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;

    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);
      } 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;
  }
}
