package org.bdware.sc.engine.hook;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bdware.sc.ContractResult;
import org.bdware.sc.JSEngine;
import org.bdware.sc.bean.ContractRequest;
import org.bdware.sc.boundry.JavaScriptEntry;
import org.bdware.sc.node.AnnotationHook;
import org.bdware.sc.node.ArgPacks;
import org.bdware.sc.node.FunctionNode;
import org.bdware.sc.util.JsonUtil;
import org.paillier.PaillierKeyPair;

import java.security.interfaces.RSAPublicKey;

public class HomomorphicEncryptHandler implements AnnotationHook {
    private static final Logger LOGGER = LogManager.getLogger(ObjToJsonHandler.class);

    private final FunctionNode fun;

    public HomomorphicEncryptHandler(FunctionNode fun) {
        this.fun = fun;
    }

    @Override
    public ArgPacks handle(JSEngine engine, ArgPacks argPacks) {
        try {
            ContractRequest input = argPacks.request;
            LOGGER.info(
                    "HomomorphicEncryptHandler--------------------------------1: "
                            + input.getRequester());
            LOGGER.info(
                    "HomomorphicEncryptHandler--------------------------------2: "
                            + this.fun.getSecretID());
            JsonElement response = (JsonElement) argPacks.ret;
            JsonElement homoEncryptConf = this.fun.getHomoEncryptConf();
            if (homoEncryptConf != null && !homoEncryptConf.isJsonNull()) {
                String res =
                        (String) JavaScriptEntry.executeContract(
                                "keyManager_1",
                                "getPubKey",
                                this.fun.getSecretID().replaceAll("\"", ""));
//                String res =
//                        JavaScriptEntry.executeContract(
//                                this.fun.getKeyManagerID(),
//                                "getPubKey",
//                                this.fun.getSecretID().replaceAll("\"", ""));
                LOGGER.info("HomomorphicEncryptHandler--------------------------------4: " + res);
                ContractResult results = JsonUtil.fromJson(res, ContractResult.class);
                String pubKeyStr = results.result.getAsString();
                LOGGER.info("HomomorphicEncryptHandler--------------------------------5: " + pubKeyStr);
                HomoVisitor.publicKey = (RSAPublicKey) PaillierKeyPair.pemToPublicKey(pubKeyStr);
//                if (homoEncryptConf.getAsJsonPrimitive().isString())
//                    homoEncryptConf = JsonParser.parseString(homoEncryptConf.getAsString());
                LOGGER.info("HomomorphicEncryptHandler--------------------------------6: " + homoEncryptConf);
                LOGGER.info("HomomorphicEncryptHandler--------------------------------7: " + argPacks.ret);
                LOGGER.info("HomomorphicEncryptHandler--------------------------------8: " + argPacks.ret.toString());
                // LOGGER.info("HomomorphicEncryptHandler--------------------------------9: " + JsonUtil.toJson(ret));
                argPacks.ret = getEncryptResult(homoEncryptConf, response);
                if (argPacks.ret != null) {
                    return argPacks;
                }
                argPacks.ret = new JsonObject();
            }
            return argPacks;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return argPacks;
    }

    private Object getEncryptResult(JsonElement homoEncryptConf, JsonElement data) {
//        if (null == homoEncryptConf || homoEncryptConf.getAsString().isEmpty()) {
//            return data;
//        }
        if (null == homoEncryptConf) {
            return data;
        }
        HomoVisitor visitor = new HomoVisitor(data);
        visitor.visit(homoEncryptConf);

        JsonElement root = visitor.get();
        System.out.println("HomoRetInvoke: " + root);
        LOGGER.info("HomoRetInvoke: " + root);
        return root;
    }
}
