package cn.chain33.javasdk.utils;

import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;

import cn.chain33.javasdk.model.enums.StorageEnum;
import cn.chain33.javasdk.model.protobuf.StorageProtobuf;
import cn.chain33.javasdk.model.protobuf.TransactionProtoBuf;
import cn.chain33.javasdk.model.protobuf.StorageProtobuf.ContentOnlyNotaryStorage.Builder;
import cn.chain33.javasdk.model.protobuf.StorageProtobuf.EncryptNotaryStorage;
import cn.chain33.javasdk.model.protobuf.StorageProtobuf.EncryptShareNotaryStorage;
import cn.chain33.javasdk.model.protobuf.StorageProtobuf.HashOnlyNotaryStorage;
import cn.chain33.javasdk.model.protobuf.StorageProtobuf.LinkNotaryStorage;
import cn.chain33.javasdk.model.protobuf.StorageProtobuf.StorageAction;

public class StorageUtil {
    
    /**
     * 
     * @description 内容存证模型
     * @param content 内容
     * @return  payload
     *
     */
    public static String createOnlyNotaryStorage(byte[] content, String execer, String privateKey) {
        Builder contentOnlyNotaryStorageBuilder = StorageProtobuf.ContentOnlyNotaryStorage.newBuilder(); 
        contentOnlyNotaryStorageBuilder.setContent(ByteString.copyFrom(content));//内容小于512k;
        cn.chain33.javasdk.model.protobuf.StorageProtobuf.StorageAction.Builder storageActionBuilder = StorageProtobuf.StorageAction.newBuilder();
        storageActionBuilder.setContentStorage(contentOnlyNotaryStorageBuilder.build());
        storageActionBuilder.setTy(StorageEnum.ContentOnlyNotaryStorage.getTy());
        StorageAction storageAction = storageActionBuilder.build();
        
        String createTxWithoutSign = TransactionUtil.createTxWithoutSign(execer.getBytes(), storageAction.toByteArray(),
        		TransactionUtil.DEFAULT_FEE, 0);
        byte[] fromHexString = HexUtil.fromHexString(createTxWithoutSign);
        TransactionProtoBuf.Transaction parseFrom = null;
        try {
            parseFrom = TransactionProtoBuf.Transaction.parseFrom(fromHexString);
        } catch (InvalidProtocolBufferException e) {
            e.printStackTrace();
        }
        TransactionProtoBuf.Transaction signProbuf = TransactionUtil.signProbuf(parseFrom, privateKey);
        String hexString = HexUtil.toHexString(signProbuf.toByteArray());
        return hexString;
    }
    
    /**
     * 
     * @description 哈希存证模型,推荐使用sha256哈希,限制256位得摘要值
     * @param hash  长度固定为32字节
     * @return payload
     * 
     */
    public static String createHashStorage(byte[] hash, String execer, String privateKey) {
        cn.chain33.javasdk.model.protobuf.StorageProtobuf.HashOnlyNotaryStorage.Builder hashStorageBuilder = StorageProtobuf.HashOnlyNotaryStorage.newBuilder();
        hashStorageBuilder.setHash(ByteString.copyFrom(hash));
        HashOnlyNotaryStorage hashOnlyNotaryStorage = hashStorageBuilder.build();
        cn.chain33.javasdk.model.protobuf.StorageProtobuf.StorageAction.Builder storageActionBuilder = StorageProtobuf.StorageAction.newBuilder();
        storageActionBuilder.setHashStorage(hashOnlyNotaryStorage);
        storageActionBuilder.setTy(StorageEnum.HashOnlyNotaryStorage.getTy());
        StorageAction storageAction = storageActionBuilder.build();
        
        String createTxWithoutSign = TransactionUtil.createTxWithoutSign(execer.getBytes(), storageAction.toByteArray(),
        		TransactionUtil.DEFAULT_FEE, 0);
        byte[] fromHexString = HexUtil.fromHexString(createTxWithoutSign);
        TransactionProtoBuf.Transaction parseFrom = null;
        try {
            parseFrom = TransactionProtoBuf.Transaction.parseFrom(fromHexString);
        } catch (InvalidProtocolBufferException e) {
            e.printStackTrace();
        }
        TransactionProtoBuf.Transaction signProbuf = TransactionUtil.signProbuf(parseFrom, privateKey);
        String hexString = HexUtil.toHexString(signProbuf.toByteArray());
        return hexString;
    }
    
    /**
     * 
     * @description 链接存证模型
     * @param link  存证内容的链接,可以写入URL,或者其他可用于定位源文件得线索.
     * @param hash  源文件得hash值,推荐使用sha256哈希,限制256位得摘要值
     * @return
     *
     */
    public static String createLinkNotaryStorage(byte[] link,byte[] hash, String execer, String privateKey) {
        cn.chain33.javasdk.model.protobuf.StorageProtobuf.LinkNotaryStorage.Builder storageBuilder = StorageProtobuf.LinkNotaryStorage.newBuilder();
        storageBuilder.setLink(ByteString.copyFrom(link));
        storageBuilder.setHash(ByteString.copyFrom(hash));
        LinkNotaryStorage linkNotaryStorage = storageBuilder.build();
        cn.chain33.javasdk.model.protobuf.StorageProtobuf.StorageAction.Builder storageActionBuilder = StorageProtobuf.StorageAction.newBuilder();
        storageActionBuilder.setLinkStorage(linkNotaryStorage);
        storageActionBuilder.setTy(StorageEnum.LinkNotaryStorage.getTy());
        StorageAction storageAction = storageActionBuilder.build();
        
        String createTxWithoutSign = TransactionUtil.createTxWithoutSign(execer.getBytes(), storageAction.toByteArray(),
        		TransactionUtil.DEFAULT_FEE, 0);
        byte[] fromHexString = HexUtil.fromHexString(createTxWithoutSign);
        TransactionProtoBuf.Transaction parseFrom = null;
        try {
            parseFrom = TransactionProtoBuf.Transaction.parseFrom(fromHexString);
        } catch (InvalidProtocolBufferException e) {
            e.printStackTrace();
        }
        TransactionProtoBuf.Transaction signProbuf = TransactionUtil.signProbuf(parseFrom, privateKey);
        String hexString = HexUtil.toHexString(signProbuf.toByteArray());
        return hexString;
    }
    
    /**
     * 
     * @description 隐私存证模型,如果一个文件需要存证,且不公开内容,可以选择将源文件通过对称加密算法加密后上链
     * @param encryptContent   存证明文内容的hash值,推荐使用sha256哈希,限制256位得摘要值
     * @param contentHash      源文件的密文,由加密key及nonce对明文加密得到该值。
     * @param nonce            加密iv,通过AES进行加密时制定随机生成的iv,解密时需要使用该值
     * @return payload
     *
     */
    public static String createEncryptNotaryStorage(byte[] encryptContent,byte[] contentHash,byte[] nonce, String key,
                                                    String value, String execer, String privateKey) {
        cn.chain33.javasdk.model.protobuf.StorageProtobuf.EncryptNotaryStorage.Builder storageBuilder = StorageProtobuf.EncryptNotaryStorage.newBuilder();
        storageBuilder.setEncryptContent(ByteString.copyFrom(encryptContent));
        storageBuilder.setContentHash(ByteString.copyFrom(contentHash));
        storageBuilder.setNonce(ByteString.copyFrom(nonce));
        storageBuilder.setKey(key);
        storageBuilder.setValue(value);
        EncryptNotaryStorage encryptNotaryStorage = storageBuilder.build();
        cn.chain33.javasdk.model.protobuf.StorageProtobuf.StorageAction.Builder storageActionBuilder = StorageProtobuf.StorageAction.newBuilder();
        storageActionBuilder.setEncryptStorage(encryptNotaryStorage);
        storageActionBuilder.setTy(StorageEnum.EncryptNotaryStorage.getTy());
        StorageAction storageAction = storageActionBuilder.build();
        
        String createTxWithoutSign = TransactionUtil.createTxWithoutSign(execer.getBytes(), storageAction.toByteArray(),
        		TransactionUtil.DEFAULT_FEE, 0);
        byte[] fromHexString = HexUtil.fromHexString(createTxWithoutSign);
        TransactionProtoBuf.Transaction parseFrom = null;
        try {
            parseFrom = TransactionProtoBuf.Transaction.parseFrom(fromHexString);
        } catch (InvalidProtocolBufferException e) {
            e.printStackTrace();
        }
        TransactionProtoBuf.Transaction signProbuf = TransactionUtil.signProbuf(parseFrom, privateKey);
        String hexString = HexUtil.toHexString(signProbuf.toByteArray());
        return hexString;
    }
    
    /**
     * 
     * @description 分享隐私存证模型
     * @param contentHash   存证明文内容的hash值,推荐使用sha256哈希,限制256位的摘要值
     * @param content       源文件的密文。
     * @param nonce         加密iv,通过AES进行加密时制定随机生成的iv,解密时需要使用该值
     * @param keyName       密钥的kdf推导路径。密钥tree父节点根据该路径可以推导出私钥key
     * @param keyWrap       加密key的wrap key。加密key随机生成,对明文进行加密,该key有私密key进行key wrap后公开。使用时,通过私密key对wrap key解密得到加密key对密文进行解密。
     * @return payload
     *
     */
    public static String createEncryptShareNotaryStorage(byte[] contentHash,byte[] content,byte[] nonce,byte[] keyName,byte[] keyWrap, String execer, String privateKey) {
        cn.chain33.javasdk.model.protobuf.StorageProtobuf.EncryptShareNotaryStorage.Builder storageBuilder = StorageProtobuf.EncryptShareNotaryStorage.newBuilder();
        storageBuilder.setContentHash(ByteString.copyFrom(contentHash));
        storageBuilder.setEncryptContent(ByteString.copyFrom(content));
//        storageBuilder.setKeyName(ByteString.copyFrom(keyName));
//        storageBuilder.setNonce(ByteString.copyFrom(nonce));
//        storageBuilder.setKeyWrap(ByteString.copyFrom(keyWrap));

        EncryptShareNotaryStorage encryptShareNotaryStorage = storageBuilder.build();
        cn.chain33.javasdk.model.protobuf.StorageProtobuf.StorageAction.Builder storageActionBuilder = StorageProtobuf.StorageAction.newBuilder();
        storageActionBuilder.setEncryptShareStorage(encryptShareNotaryStorage);
        storageActionBuilder.setTy(StorageEnum.EncryptShareNotaryStorage.getTy());
        StorageAction storageAction = storageActionBuilder.build();

        String createTxWithoutSign = TransactionUtil.createTxWithoutSign(execer.getBytes(), storageAction.toByteArray(),
        		TransactionUtil.DEFAULT_FEE, 0);
        byte[] fromHexString = HexUtil.fromHexString(createTxWithoutSign);
        TransactionProtoBuf.Transaction parseFrom = null;
        try {
            parseFrom = TransactionProtoBuf.Transaction.parseFrom(fromHexString);
        } catch (InvalidProtocolBufferException e) {
            e.printStackTrace();
        }
        TransactionProtoBuf.Transaction signProbuf = TransactionUtil.signProbuf(parseFrom, privateKey);
        String hexString = HexUtil.toHexString(signProbuf.toByteArray());
        return hexString;
    }
}