package info.blockchain.wallet.ui;
import java.math.BigInteger;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Handler;
import android.preference.PreferenceManager;
//import android.util.Log;
import android.util.Pair;
import android.widget.EditText;
import android.widget.Toast;
import com.google.bitcoin.core.Address;
import com.google.bitcoin.core.ECKey;
import com.google.bitcoin.core.NetworkParameters;
import com.google.bitcoin.params.MainNetParams;
import com.google.bitcoin.uri.BitcoinURI;
import piuk.blockchain.android.EventListeners;
import piuk.blockchain.android.MyRemoteWallet;
import piuk.blockchain.android.Constants;
import piuk.blockchain.android.R;
import piuk.blockchain.android.WalletApplication;
import piuk.blockchain.android.WalletApplication.AddAddressCallback;
import piuk.blockchain.android.SuccessCallback;
import piuk.blockchain.android.util.WalletUtils;
public class AddressManager {
private MyRemoteWallet blockchainWallet = null;
private WalletApplication application = null;
private Activity activity = null;
private static AddressManager instance = null;
protected Handler handler;
public static AddressManager getInstance(MyRemoteWallet remoteWallet, WalletApplication application, Activity activity) {
if(instance == null) {
instance = new AddressManager(remoteWallet, application, activity);
}
return instance;
}
public AddressManager(MyRemoteWallet remoteWallet, WalletApplication application, Activity activity) {
this.blockchainWallet = remoteWallet;
this.application = application;
this.activity = activity;
this.handler = new Handler();
}
public BigInteger getBalance(final String address) {
return this.blockchainWallet.getBalance(address);
}
public boolean isWatchOnly(String address) {
try {
return this.blockchainWallet.isWatchOnly(address);
} catch (Exception e) {
return false;
}
}
public boolean canAddAddressBookEntry(final String address, final String label) {
if (blockchainWallet.findAddressBookEntry(address) == null)
return true;
else
return false;
}
public boolean handleAddAddressBookEntry(final String address, final String label, final SuccessCallback callback) {
try {
if (blockchainWallet == null)
return true;
if (! BitcoinAddressCheck.isValidAddress(address)) {
Toast.makeText(activity, R.string.invalid_bitcoin_address, Toast.LENGTH_LONG).show();
return false;
}
blockchainWallet.addAddressBookEntry(address, label);
application.saveWallet(new SuccessCallback() {
@Override
public void onSuccess() {
// Log.d("AddressManager", "AddressManager saveWallet onSuccess");
EventListeners.invokeWalletDidChange();
callback.onSuccess();
}
@Override
public void onFail() {
// Log.d("AddressManager", "AddressManager saveWallet onFail");
callback.onFail();
}
});
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
public void handleAddWatchOnly(String data) throws Exception {
String address;
try {
address = new Address(Constants.NETWORK_PARAMETERS, data).toString();
} catch (Exception e) {
try {
BitcoinURI uri = new BitcoinURI(data);
address = uri.getAddress().toString();
} catch (Exception e1) {
Toast.makeText(activity, R.string.send_coins_fragment_receiving_address_error, Toast.LENGTH_LONG).show();
return;
}
}
final String finalAddress = address;
try {
application.getRemoteWallet().addWatchOnly(finalAddress, "android_watch_only");
application.saveWallet(new SuccessCallback() {
@Override
public void onSuccess() {
// Log.d("AddressManager", "AddressManager onSavedAddress onSuccess");
application.checkIfWalletHasUpdatedAndFetchTransactions(blockchainWallet.getTemporyPassword(), new SuccessCallback() {
@Override
public void onSuccess() {
Toast.makeText(activity, R.string.scanned_watch_only_address, Toast.LENGTH_LONG).show();
}
public void onFail() {
Toast.makeText(activity, R.string.scanned_watch_only_address, Toast.LENGTH_LONG).show();
}
});
}
@Override
public void onFail() {
Toast.makeText(activity, R.string.error_scanning_address, Toast.LENGTH_LONG).show();
}
});
} catch (Exception e) {
Toast.makeText(activity, e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
}
}
public void handleScanPrivateKeyPair(final ECKey key, final SuccessCallback callback) throws Exception {
new Thread() {
public void run() {
try {
final String address;
if (key.isCompressed()) {
address = key.toAddressCompressed(MainNetParams.get()).toString();
} else {
address = key.toAddressUnCompressed(MainNetParams.get()).toString();
}
application.addKeyToWallet(key, key.toAddress(MainNetParams.get()).toString(), null, 0,
new AddAddressCallback() {
public void onSavedAddress(String address) {
application.checkIfWalletHasUpdatedAndFetchTransactions(blockchainWallet.getTemporyPassword(), new SuccessCallback() {
@Override
public void onSuccess() {
Toast.makeText(activity, R.string.scanned_private_key, Toast.LENGTH_LONG).show();
if (callback != null)
callback.onSuccess();
}
public void onFail() {
Toast.makeText(activity, R.string.scanned_private_key, Toast.LENGTH_LONG).show();
if (callback != null)
callback.onFail();
}
});
}
public void onError(String reason) {
Toast.makeText(activity, R.string.error_scanning_private_key, Toast.LENGTH_LONG).show();
if (callback != null)
callback.onFail();
}
});
} catch (final Exception e) {
e.printStackTrace();
if (callback != null)
callback.onFail();
handler.post(new Runnable() {
public void run() {
}
});
}
}
}.start();
}
public void setAddressLabel(final String address, final String label,
final Runnable checkIfWalletHasUpdatedAndFetchTransactionsFail,
final Runnable settingLabelFail,
final Runnable syncingWalletFail) {
if (blockchainWallet == null)
return;
application.checkIfWalletHasUpdatedAndFetchTransactions(blockchainWallet.getTemporyPassword(), new SuccessCallback() {
@Override
public void onSuccess() {
try {
blockchainWallet.addLabel(address, label);
new Thread() {
@Override
public void run() {
try {
blockchainWallet.remoteSave();
System.out.println("invokeWalletDidChange()");
EventListeners.invokeWalletDidChange();
} catch (Exception e) {
e.printStackTrace();
application.writeException(e);
application.getHandler().post(syncingWalletFail);
}
}
}.start();
} catch (Exception e) {
e.printStackTrace();
application.getHandler().post(settingLabelFail);
}
}
@Override
public void onFail() {
application.getHandler().post(checkIfWalletHasUpdatedAndFetchTransactionsFail);
}
});
}
public void newAddress(final AddAddressCallback callback) {
final ECKey key = application.getRemoteWallet().generateECKey();
addKeyToWallet(key, key.toAddress(MainNetParams.get()).toString(), null, 0, callback);
}
public void addKeyToWallet(final ECKey key, final String address, final String label, final int tag,
final AddAddressCallback callback) {
if (blockchainWallet == null) {
callback.onError("Wallet null.");
return;
}
if (application.isInP2PFallbackMode()) {
callback.onError("Error saving wallet.");
return;
}
try {
final boolean success = blockchainWallet.addKey(key, address, label);
if (success) {
application.localSaveWallet();
application.saveWallet(new SuccessCallback() {
@Override
public void onSuccess() {
application.checkIfWalletHasUpdated(blockchainWallet.getTemporyPassword(), false, new SuccessCallback() {
@Override
public void onSuccess() {
try {
ECKey key = blockchainWallet.getECKey(address);
//TODO fix so address equality matches
/*
Log.d("AddressManager", "AddressManager addKeyToWallet address1 " + address); // compressed address
Log.d("AddressManager", "AddressManager addKeyToWallet address2 " + key.toAddress(MainNetParams.get()).toString()); // compressed address
Log.d("AddressManager", "AddressManager addKeyToWallet address3 " + key.toAddressUnCompressed(MainNetParams.get()).toString());
Log.d("AddressManager", "AddressManager addKeyToWallet address4 " + key.toAddressCompressed(MainNetParams.get()).toString());
*/
if (key != null && (key.toAddressCompressed(MainNetParams.get()).toString().equals(address) ||
key.toAddressUnCompressed(MainNetParams.get()).toString().equals(address))) {
callback.onSavedAddress(address);
} else {
blockchainWallet.removeKey(key);
callback.onError("WARNING! Wallet saved but address doesn't seem to exist after re-read.");
}
} catch (Exception e) {
blockchainWallet.removeKey(key);
callback.onError("WARNING! Error checking if ECKey is valid on re-read.");
}
}
@Override
public void onFail() {
blockchainWallet.removeKey(key);
callback.onError("WARNING! Error checking if address was correctly saved.");
}
});
}
@Override
public void onFail() {
blockchainWallet.removeKey(key);
callback.onError("Error saving wallet");
}
});
} else {
callback.onError("addKey returned false");
}
} catch (Exception e) {
e.printStackTrace();
application.writeException(e);
callback.onError(e.getLocalizedMessage());
}
}
public boolean deleteAddressBook(final String address) {
try {
if (blockchainWallet == null)
return true;
blockchainWallet.deleteAddressBook(address);
application.saveWallet(new SuccessCallback() {
@Override
public void onSuccess() {
EventListeners.invokeWalletDidChange();
}
@Override
public void onFail() {
}
});
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
public boolean archiveAddress(final String address) {
return setAddressTag(address, 2);
}
public boolean unArchiveAddress(final String address) {
return setAddressTag(address, 0);
}
private boolean setAddressTag(final String address, long tag) {
try {
if (blockchainWallet == null)
return true;
blockchainWallet.setTag(address, tag);
application.saveWallet(new SuccessCallback() {
@Override
public void onSuccess() {
EventListeners.invokeWalletDidChange();
}
@Override
public void onFail() {
}
});
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
public void setDefaultAddress(final String address) {
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
prefs.edit().putString(Constants.PREFS_KEY_SELECTED_ADDRESS, address.toString()).commit();
}
}