package org.bdware.sc.boundry.utils;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bdware.bdledger.api.grpc.Client;
import org.bdware.bdledger.api.grpc.pb.CommonProto.Transaction;
import org.bdware.bdledger.api.grpc.pb.CommonProto.TransactionType;
import org.bdware.bdledger.api.grpc.pb.LedgerProto.SendTransactionResponse;
import org.bdware.bdledger.api.grpc.pb.QueryProto.GetTransactionByHashResponse;
import org.bdware.sc.boundry.JavaScriptEntry;
import org.bdware.sc.compiler.PermissionStub;
import org.bdware.sc.engine.JSONTool;
import org.bdware.sc.node.Permission;
import org.bdware.sc.util.HashUtil;
import wrp.jdk.nashorn.api.scripting.ScriptObjectMirror;
import wrp.jdk.nashorn.internal.runtime.PropertyMap;
import wrp.jdk.nashorn.internal.runtime.ScriptObject;
import wrp.jdk.nashorn.internal.scripts.JO;

import java.security.SecureRandom;

@PermissionStub(permission = Permission.Ledger)
public class LedgerUtil {
    static SecureRandom random = new SecureRandom((System.currentTimeMillis() + "").getBytes());

    public static Object getLedgerParams() {
        //format:{nodes:[{ip:ip,port:port}]}
        String ledgerParam = JavaScriptEntry.get.syncGet("", "getLedgerParams", "");
        JsonElement jo = JsonParser.parseString(ledgerParam);
        return JSONTool.convertJsonElementToMirror(jo);
    }

    public static Client getDefaultClient() {
        String ledgerParam = JavaScriptEntry.get.syncGet("", "getLedgerParams", "");
        JsonElement jo = JsonParser.parseString(ledgerParam);
        JsonObject param = jo.getAsJsonObject().get("nodes").getAsJsonArray().get(0).getAsJsonObject();
        return new Client(param.get("ip").getAsString(), param.get("port").getAsInt());
    }

    public static Client getClient(ScriptObjectMirror str) {
        return new Client((String) str.get("ip"), Integer.parseInt(str.get("port").toString()));
    }

    static Logger LOGGER = LogManager.getLogger(LedgerUtil.class);

    public static ScriptObject queryByHash(Client c, ScriptObjectMirror str) {
        LOGGER.info("TID:" + Thread.currentThread().getId());
        String ledger = str.get("ledger").toString();
        String hash = str.get("hash").toString();
        JO ret = new JO(PropertyMap.newMap());
        GetTransactionByHashResponse result = c.getTransactionByHashSync(ledger, hash);
        Transaction transaction = result.getTransaction();
        ret.put("from", HashUtil.byteArray2Str(transaction.getFrom().toByteArray(), 0), false);
        ret.put("to", HashUtil.byteArray2Str(transaction.getTo().toByteArray(), 0), false);
        ret.put("type", transaction.getType().toString(), false);
        ret.put("data", new String(transaction.getData().toByteArray()), false);
        ret.put("blockHsah", HashUtil.byteArray2Str(transaction.getBlockHash().toByteArray(), 0), false);
        return ret;
    }

    public static String sendTransaction(Client c, ScriptObjectMirror str) {
        String ledger = str.get("ledger").toString();
        String from = str.get("from").toString();
        String to = str.get("to").toString();
        String data = str.get("data").toString();
        SendTransactionResponse result =
                c.sendTransactionSync(
                        ledger,
                        TransactionType.MESSAGE,
                        from,
                        random.nextLong(),
                        to,
                        data.getBytes());
        return HashUtil.byteArray2Str(result.getHash().toByteArray(), 0);
    }
}
