package org.bdware.sc.commParser.BDLedger;

import org.bdware.sc.util.HashUtil;
import org.bdware.sc.util.JsonUtil;

import java.io.*;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.Map;

public class Transaction {
    public byte[] srcID;
    public byte[] dstID;
    public long nonce;
    public int type;
    public byte[] data;
    //扩展字段
    public int timestamp;
    public byte[] hash;

    public static Transaction fromBytes(byte[] bytes) {
        try {
            Transaction trans = new Transaction();
            DataInputStream bin = new DataInputStream(new ByteArrayInputStream(bytes));
            trans.srcID = new byte[20];
            trans.dstID = new byte[20];
            bin.read(trans.srcID);
            bin.read(trans.dstID);
            trans.nonce = bin.readLong();
            trans.type = bin.readInt();
            int len = bin.readInt();
            trans.data = new byte[len];
            bin.read(trans.data);
            return trans;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public byte[] getTransactionHash() {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            byte[] encoded = md.digest(toHashByteArray());
            byte[] truned = HashUtil.truncation(encoded, 20);
            System.out.println("[Transaction] encoded:" + HashUtil.byteArray2Str(encoded) + " ==> "
                    + HashUtil.byteArray2Str(truned));
            return truned;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public String toJson() {
        Map<String, String> ret = new HashMap<>();
        ret.put("SrcID", HashUtil.byteArray2Str(srcID));
        ret.put("dstID", HashUtil.byteArray2Str(dstID));
        ret.put("nonce", String.valueOf(nonce));
        ret.put("type", String.valueOf(type));
        ret.put("data", HashUtil.byteArray2Str(data));
        return JsonUtil.toJson(ret);

    }

    public byte[] toByteArray() {
        try {
            ByteArrayOutputStream bo = new ByteArrayOutputStream();
            DataOutputStream dd = new DataOutputStream(bo);
            dd.write(srcID);
            dd.write(dstID);
            dd.writeLong(nonce);
            dd.writeInt(type);
            dd.writeInt(data.length);
            dd.write(data);
            return bo.toByteArray();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    public byte[] toHashByteArray() {
        try {
            ByteArrayOutputStream bo = new ByteArrayOutputStream();
            DataOutputStream dd = new DataOutputStream(bo);
            dd.write(srcID);
            dd.write(dstID);
            dd.writeLong(HashUtil.toLittleEndian(nonce));
            dd.writeInt(HashUtil.toLittleEndian(type));
            dd.write(data);
            return bo.toByteArray();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
}