package net.bither.bitherj.core;

import net.bither.bitherj.api.GetHDMBIdRandomApi;
import net.bither.bitherj.api.UploadHDMBidApi;
import net.bither.bitherj.api.http.HttpException;
import net.bither.bitherj.crypto.ECKey;
import net.bither.bitherj.crypto.EncryptedData;
import net.bither.bitherj.crypto.SecureCharSequence;
import net.bither.bitherj.db.AbstractDb;

import org.spongycastle.util.encoders.Base64;

import net.bither.bitherj.utils.Utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.charset.Charset;
import java.security.SecureRandom;
import java.security.SignatureException;

public class HDMBId {
    private static final Logger log = LoggerFactory.getLogger(HDMBId.class);

    public final static String BITID_STRING = "bitid://hdm.bither.net/%s/password/%s/%d";
    private static HDMBId hdmbidCache;

    private String address;
    private EncryptedData encryptedBitherPassword;
    private byte[] decryptedPassword;
    private long serviceRandom;


    public HDMBId(String address) {
        this.address = address;
    }


    public HDMBId(String addressForBitherId, String encryptedBitherPassword) {
        this(addressForBitherId, new EncryptedData(encryptedBitherPassword));
    }


    public HDMBId(String addressForBitherId, EncryptedData encryptedBitherPassword) {
        this.address = addressForBitherId;
        this.encryptedBitherPassword = encryptedBitherPassword;
    }

    public String getPreSignString() throws Exception {
        SecureRandom random = new SecureRandom();
        decryptedPassword = new byte[32];
        random.nextBytes(decryptedPassword);
        GetHDMBIdRandomApi getHDMBIdRandomApi = new GetHDMBIdRandomApi(address);
        getHDMBIdRandomApi.handleHttpGet();
        serviceRandom = getHDMBIdRandomApi.getResult();
        String message = Utils.format(BITID_STRING, address, Utils.bytesToHexString(decryptedPassword), serviceRandom);
        byte[] hash = Utils.getPreSignMessage(message);
        return Utils.bytesToHexString(hash);


    }

    public void setSignature(String signString, SecureCharSequence secureCharSequence) throws Exception {
        String message = Utils.format(BITID_STRING, address, Utils.bytesToHexString(decryptedPassword), serviceRandom);
        byte[] hash = Utils.getPreSignMessage(message);
        ECKey key = ECKey.signedMessageToKey(hash, Utils.hexStringToByteArray(signString));
        if (Utils.compareString(address, key.toAddress())) {
            throw new SignatureException();

        }
        String hotAddress = AddressManager.getInstance().getHdmKeychain().getFirstAddressFromDb();
        UploadHDMBidApi uploadHDMBidApi = new UploadHDMBidApi(address, hotAddress, Utils.hexStringToByteArray(signString), decryptedPassword);
        uploadHDMBidApi.handleHttpPost();
        boolean result = uploadHDMBidApi.getResult();
        if (result) {
            encryptedBitherPassword = new EncryptedData(decryptedPassword, secureCharSequence);
            AbstractDb.addressProvider.addHDMBId(HDMBId.this);
        } else {
            throw new HttpException("UploadHDMBidApi error");
        }


    }

    public String getAddress() {
        return address;
    }


    public String getEncryptedBitherPasswordString() {
        return encryptedBitherPassword.toEncryptedString();
    }

    public void setEncryptedData(EncryptedData encryptedData) {
        this.encryptedBitherPassword = encryptedData;
    }

    public void saveEncryptedBitherPassword() {
        AbstractDb.addressProvider.changeHDBIdPassword(HDMBId.this);
    }

    public byte[] decryptHDMBIdPassword(CharSequence password) {
        decryptedPassword = encryptedBitherPassword.decrypt(password);
        return decryptedPassword;
    }


    public synchronized static HDMBId getHDMBidFromDb() {
        if (hdmbidCache != null) {
            return hdmbidCache;
        }
        hdmbidCache = AbstractDb.addressProvider.getHDMBId();
        if (hdmbidCache == null || Utils.isEmpty(hdmbidCache.getAddress()) ||
                Utils.isEmpty(hdmbidCache.getEncryptedBitherPasswordString())) {
            hdmbidCache = null;
        }
        return hdmbidCache;
    }

}

@@ -73,24 +73,70 @@
 dRandomApi;%0A
+import net.bither.bitherj.api.RecoveryHDMApi;%0A
 import net.b
@@ -166,24 +166,24 @@
 dHDMBidApi;%0A
-
 import net.b
@@ -656,16 +656,39 @@
 ception;
+%0Aimport java.util.List;
 %0A%0Apublic
@@ -2155,22 +2155,16 @@
 String, 
-Secure
 CharSequ
@@ -3189,16 +3189,16 @@
 rror%22);%0A
-
         
@@ -3200,32 +3200,951 @@
      %7D%0A%0A%0A    %7D%0A%0A
+    public List%3CHDMAddress.Pubs%3E recoverHDM(String signString, CharSequence secureCharSequence) throws Exception %7B%0A        String message = Utils.format(BITID_STRING, address, Utils.bytesToHexString(decryptedPassword), serviceRandom);%0A        byte%5B%5D hash = Utils.getPreSignMessage(message);%0A        ECKey key = ECKey.signedMessageToKey(hash, Utils.hexStringToByteArray(signString));%0A        if (Utils.compareString(address, key.toAddress())) %7B%0A            throw new SignatureException();%0A%0A        %7D%0A%0A        RecoveryHDMApi recoveryHDMApi = new RecoveryHDMApi(address, Utils.hexStringToByteArray(signString), decryptedPassword);%0A        recoveryHDMApi.handleHttpPost();%0A        List%3CHDMAddress.Pubs%3E result = recoveryHDMApi.getResult();%0A        encryptedBitherPassword = new EncryptedData(decryptedPassword, secureCharSequence);%0A        AbstractDb.addressProvider.addHDMBId(HDMBId.this);%0A        return result;%0A%0A%0A    %7D%0A%0A
     public Strin

add recoveryHDM