/**
   * Create a Trezor hard wallet from a backup summary, decrypting it with a password created from
   * the Trezor supplied entropy
   */
  private boolean createTrezorHardWallet() {

    // Get the model that contains the selected wallet backup to use
    SelectBackupSummaryModel selectedBackupSummaryModel =
        getWizardModel().getSelectBackupSummaryModel();

    if (selectedBackupSummaryModel == null
        || selectedBackupSummaryModel.getValue() == null
        || selectedBackupSummaryModel.getValue().getFile() == null) {
      log.debug("No wallet backup to use from the model");
      return false;
    }

    log.debug(
        "Loading hard wallet backup '" + selectedBackupSummaryModel.getValue().getFile() + "'");
    try {
      // For Trezor hard wallets the backups are encrypted with the entropy derived password
      String walletPassword = null;
      Optional<HardwareWalletService> hardwareWalletService =
          CoreServices.getOrCreateHardwareWalletService();
      if (hardwareWalletService.isPresent()
          && hardwareWalletService.get().getContext().getEntropy().isPresent()) {
        walletPassword =
            Hex.toHexString(hardwareWalletService.get().getContext().getEntropy().get());
      }

      // Check there is a wallet password - if not then cannot decrypt backup
      if (walletPassword == null) {
        log.debug(
            "Cannot work out the password to decrypt the backup - there is no entropy from the Trezor");
        return false;
      }
      KeyParameter backupAESKey =
          AESUtils.createAESKey(
              walletPassword.getBytes(Charsets.UTF_8), WalletManager.scryptSalt());

      WalletId loadedWalletId =
          BackupManager.INSTANCE.loadZipBackup(
              selectedBackupSummaryModel.getValue().getFile(), backupAESKey);

      // Attempt to open the wallet
      final Optional<WalletSummary> walletSummaryOptional =
          WalletManager.INSTANCE.openWalletFromWalletId(
              InstallationManager.getOrCreateApplicationDataDirectory(),
              loadedWalletId,
              walletPassword);

      // If the wallet is present then it was opened successfully
      return walletSummaryOptional.isPresent();

    } catch (Exception e) {
      log.error("Failed to restore Trezor hard wallet.", e);
    }

    // Must have failed to be here
    return false;
  }
  public void update(List<Client> clientSet, List<Payment> payments) {
    Object[] columnNames =
        new Object[] {
          "#Cliente",
          "Nombre",
          "Apellido",
          "Celular",
          "Inscripción",
          "Domicilio",
          "Correo electrónico",
          "Próxima cuota"
        };

    Map<Integer, List<Payment>> paymentsByIds = new HashMap<>(clientSet.size());
    for (Payment payment : payments) {
      paymentsByIds.getOrDefault(payment.getClientId(), new ArrayList<>()).add(payment);

      List<Payment> idPayments = paymentsByIds.get(payment.getClientId());
      if (idPayments == null) {
        idPayments = new ArrayList<>();
        paymentsByIds.put(payment.getClientId(), idPayments);
      }
      idPayments.add(payment);
    }

    Object[][] data = new Object[clientSet.size()][columnNames.length];
    int i = 0;
    for (Client client : clientSet) {
      data[i][COLUMN_CLIENT] = client;
      data[i][COLUMN_FIRSTNAME] = client.getFirstName();
      data[i][COLUMN_LASTNAME] = client.getLastName();
      data[i][COLUMN_PHONENUMBER] = client.getPhoneNumber();
      data[i][COLUMN_INSCRIPTIONDATE] = client.getInscriptionDate().format(Utils.DATE_FORMATTER);
      data[i][COLUMN_HOMEADDRESS] = client.getHomeAddress();
      data[i][COLUMN_MAIL] = client.getMail();

      String finalString = "Nunca";
      Optional<Payment> lastPayment = getClientLastPayment(client, paymentsByIds);
      if (lastPayment.isPresent()) {
        LocalDate nextMonthToPay = lastPayment.get().getMonthDate().plusMonths(1);
        Period periodBetweenNowAndNextMonthToPay = Period.between(LocalDate.now(), nextMonthToPay);
        finalString = readablePeriod(periodBetweenNowAndNextMonthToPay);
      }
      data[i][COLUMN_NEXTPAYMENT] = finalString;
      i++;
    }
    TableModel tableModel = new DefaultTableModel(data, columnNames);
    setModel(tableModel);

    RowFilter<Object, Object> filter =
        new RowFilter<Object, Object>() {
          @Override
          public boolean include(Entry entry) {
            Client client = (Client) entry.getValue(COLUMN_CLIENT);
            if (!inactiveClientsVisible && client.isInactive()) {
              return false;
            }

            if (filteringWords == null) {
              return true;
            }

            for (String word : filteringWords) {
              if (!entryContainsWord(entry, word)) {
                return false;
              }
            }
            return true;
          }
        };

    TableRowSorter<TableModel> sorter = new TableRowSorter<>(tableModel);
    sorter.setRowFilter(filter);
    setRowSorter(sorter);
  }
  /** Create a wallet from a seed phrase and a backup summary (chosen by the user) */
  private boolean createWalletFromSeedPhrase(List<String> seedPhrase) {

    if (!verifySeedPhrase(seedPhrase)) {
      return false;
    }

    // Get the model that contains the selected wallet backup to use
    SelectBackupSummaryModel selectedBackupSummaryModel =
        getWizardModel().getSelectBackupSummaryModel();

    if (selectedBackupSummaryModel == null
        || selectedBackupSummaryModel.getValue() == null
        || selectedBackupSummaryModel.getValue().getFile() == null) {
      log.debug("No wallet backup to use from the model");
      return false;
    }

    log.debug(
        "Loading soft wallet backup '" + selectedBackupSummaryModel.getValue().getFile() + "'");
    try {

      WalletId loadedWalletId =
          BackupManager.INSTANCE.loadZipBackup(
              selectedBackupSummaryModel.getValue().getFile(), seedPhrase);

      // Locate the installation directory
      File applicationDataDirectory = InstallationManager.getOrCreateApplicationDataDirectory();

      // Work out what the wallet credentials was from the encrypted value stored in the
      // WalletSummary
      SeedPhraseGenerator seedPhraseGenerator = new Bip39SeedPhraseGenerator();
      byte[] seed = seedPhraseGenerator.convertToSeed(seedPhrase);

      String walletRoot =
          applicationDataDirectory.getAbsolutePath()
              + File.separator
              + WalletManager.createWalletRoot(loadedWalletId);
      WalletSummary walletSummary =
          WalletManager.getOrCreateWalletSummary(new File(walletRoot), loadedWalletId);

      KeyParameter backupAESKey = AESUtils.createAESKey(seed, WalletManager.scryptSalt());
      byte[] decryptedPaddedWalletPasswordBytes =
          org.multibit.commons.crypto.AESUtils.decrypt(
              walletSummary.getEncryptedPassword(),
              backupAESKey,
              WalletManager.aesInitialisationVector());
      byte[] decryptedWalletPasswordBytes =
          WalletManager.unpadPasswordBytes(decryptedPaddedWalletPasswordBytes);
      String decryptedWalletPassword = new String(decryptedWalletPasswordBytes, "UTF8");

      // Attempt to open the wallet
      final Optional<WalletSummary> walletSummaryOptional =
          WalletManager.INSTANCE.openWalletFromWalletId(
              InstallationManager.getOrCreateApplicationDataDirectory(),
              loadedWalletId,
              decryptedWalletPassword);

      // If the wallet is present then it was opened successfully
      return walletSummaryOptional.isPresent();

    } catch (Exception e) {
      log.error("Failed to restore wallet from seed phrase.", e);
    }

    // Must have failed to be here
    return false;
  }