<commit_before>package org.multibit.hd.core.managers;

import com.google.bitcoin.core.ECKey;
import com.google.bitcoin.core.Wallet;
import com.google.bitcoin.crypto.KeyCrypter;
import com.google.bitcoin.crypto.KeyCrypterScrypt;
import com.google.bitcoin.store.WalletProtobufSerializer;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import org.multibit.hd.core.api.WalletData;
import org.multibit.hd.core.api.WalletId;
import org.multibit.hd.core.config.Configurations;
import org.multibit.hd.core.exceptions.WalletLoadException;
import org.multibit.hd.core.exceptions.WalletSaveException;
import org.multibit.hd.core.exceptions.WalletVersionException;
import org.multibit.hd.core.services.BitcoinNetworkService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongycastle.asn1.sec.SECNamedCurves;
import org.spongycastle.asn1.x9.X9ECParameters;

import java.io.*;
import java.math.BigInteger;
import java.util.Collection;
import java.util.List;

/**
 *  <p>Manager to provide the following to core users:<br>
 *  <ul>
 *  <li>create wallet</li>
 *  <li>load wallet</li>
 *  <li>store wallet</li>
 * <li> tracks the current wallet and the list of wallet directories</li>
 *  </ul>
 */
public enum WalletManager {
  INSTANCE;

  private static WalletProtobufSerializer walletProtobufSerializer;

  static {
    walletProtobufSerializer = new WalletProtobufSerializer();
    // TODO was originally multibit protobuf serializer - ok ?
  }

  private static final Logger log = LoggerFactory.getLogger(WalletManager.class);

  public static final String WALLET_DIRECTORY_PREFIX = "mbhd";

  public static final String SEPARATOR = "-";

  // The format of the wallet directories is WALLET_DIRECTORY_PREFIX + a wallet id.
  // A walletid is 5 groups of 4 bytes in lowercase hex, with a "-' separator e.g. mbhd-11111111-22222222-33333333-44444444-55555555
  public static final String REGEX_FOR_WALLET_DIRECTORY = "^" + WALLET_DIRECTORY_PREFIX + SEPARATOR + "[0-9a-f]{8}"
          + SEPARATOR + "[0-9a-f]{8}" + SEPARATOR + "[0-9a-f]{8}" + SEPARATOR + "[0-9a-f]{8}" + SEPARATOR + "[0-9a-f]{8}$";

  /**
   * The wallet version number for protobuf encrypted wallets - compatible with MultiBit
   */
  public static final int ENCRYPTED_WALLET_VERSION = 3; // TODO - need a new version when the wallet format is modified

  public static final String MBHD_WALLET_NAME = "mbhd.wallet";

  private File applicationDataDirectory;

  private List<File> walletDirectories;

  private Optional<WalletData> currentWalletData;

  /**
   * Initialise enum, load up the available wallets and find the current wallet
   *
   * @param applicationDataDirectory The directory in which to store and read wallets.
   */
  public void initialise(File applicationDataDirectory) {
    this.applicationDataDirectory = applicationDataDirectory;

    // Work out the list of available wallets in the application data directory
    walletDirectories = findWalletDirectories(applicationDataDirectory);

    // TODO enable user to switch wallets - currently using the first

    // If a wallet directory is present try to load it.
    // TODO catch wallet load exceptions and report
    if (!walletDirectories.isEmpty()) {
      String walletFilename = walletDirectories.get(0) + File.separator + MBHD_WALLET_NAME;
      WalletData walletData = loadFromFile(new File(walletFilename));
      currentWalletData = Optional.of(walletData);
    } else {
      currentWalletData = Optional.absent();
    }
  }

  /**
   * Create a wallet that contains only a single, random private key.
   * This is stored in the MultiBitHD application data directory
   * The name of the wallet file is derived from the seed.
   * If the wallet file already exists it is loaded and returned (and the input password is not used)<commit_msg>Introduced Optional.absent() to ensure clean shutdown<commit_after>package org.multibit.hd.core.managers;

import com.google.bitcoin.core.ECKey;
import com.google.bitcoin.core.Wallet;
import com.google.bitcoin.crypto.KeyCrypter;
import com.google.bitcoin.crypto.KeyCrypterScrypt;
import com.google.bitcoin.store.WalletProtobufSerializer;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import org.multibit.hd.core.api.WalletData;
import org.multibit.hd.core.api.WalletId;
import org.multibit.hd.core.config.Configurations;
import org.multibit.hd.core.exceptions.WalletLoadException;
import org.multibit.hd.core.exceptions.WalletSaveException;
import org.multibit.hd.core.exceptions.WalletVersionException;
import org.multibit.hd.core.services.BitcoinNetworkService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongycastle.asn1.sec.SECNamedCurves;
import org.spongycastle.asn1.x9.X9ECParameters;

import java.io.*;
import java.math.BigInteger;
import java.util.Collection;
import java.util.List;

/**
 *  <p>Manager to provide the following to core users:<br>
 *  <ul>
 *  <li>create wallet</li>
 *  <li>load wallet</li>
 *  <li>store wallet</li>
 * <li> tracks the current wallet and the list of wallet directories</li>
 *  </ul>
 */
public enum WalletManager {
  INSTANCE;

  private static WalletProtobufSerializer walletProtobufSerializer;

  static {
    walletProtobufSerializer = new WalletProtobufSerializer();
    // TODO was originally multibit protobuf serializer - ok ?
  }

  private static final Logger log = LoggerFactory.getLogger(WalletManager.class);

  public static final String WALLET_DIRECTORY_PREFIX = "mbhd";

  public static final String SEPARATOR = "-";

  // The format of the wallet directories is WALLET_DIRECTORY_PREFIX + a wallet id.
  // A walletid is 5 groups of 4 bytes in lowercase hex, with a "-' separator e.g. mbhd-11111111-22222222-33333333-44444444-55555555
  public static final String REGEX_FOR_WALLET_DIRECTORY = "^" + WALLET_DIRECTORY_PREFIX + SEPARATOR + "[0-9a-f]{8}"
          + SEPARATOR + "[0-9a-f]{8}" + SEPARATOR + "[0-9a-f]{8}" + SEPARATOR + "[0-9a-f]{8}" + SEPARATOR + "[0-9a-f]{8}$";

  /**
   * The wallet version number for protobuf encrypted wallets - compatible with MultiBit
   */
  public static final int ENCRYPTED_WALLET_VERSION = 3; // TODO - need a new version when the wallet format is modified

  public static final String MBHD_WALLET_NAME = "mbhd.wallet";

  private File applicationDataDirectory;

  private List<File> walletDirectories = Lists.newArrayList();

  private Optional<WalletData> currentWalletData=Optional.absent();

  /**
   * Initialise enum, load up the available wallets and find the current wallet
   *
   * @param applicationDataDirectory The directory in which to store and read wallets.
   */
  public void initialise(File applicationDataDirectory) {
    this.applicationDataDirectory = applicationDataDirectory;

    // Work out the list of available wallets in the application data directory
    walletDirectories = findWalletDirectories(applicationDataDirectory);

    // TODO enable user to switch wallets - currently using the first

    // If a wallet directory is present try to load it.
    // TODO catch wallet load exceptions and report
    if (!walletDirectories.isEmpty()) {
      String walletFilename = walletDirectories.get(0) + File.separator + MBHD_WALLET_NAME;
      WalletData walletData = loadFromFile(new File(walletFilename));
      currentWalletData = Optional.of(walletData);
    } else {
      currentWalletData = Optional.absent();
    }
  }

  /**
   * Create a wallet that contains only a single, random private key.
   * This is stored in the MultiBitHD application data directory
   * The name of the wallet file is derived from the seed.
   * If the wallet file already exists it is loaded and returned (and the input password is not used)
{'fraction_non_alphanumeric': 0.09447915338518424, 'fraction_numerical': 0.016575290067576184, 'mean_word_length': 4.246822742474916, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 10, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6962653', 'n_tokens_mistral': 2446, 'n_tokens_neox': 2365, 'n_words': 669}