package org.bdware.sc.controlproxy;

import com.google.gson.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bdware.doip.audit.EndpointConfig;
import org.bdware.doip.audit.client.AuditDoipClient;
import org.bdware.doip.audit.client.AuditIrpClient;
import org.bdware.doip.audit.config.TempConfigStorage;
import org.bdware.doip.audit.writer.AuditConfig;
import org.bdware.doip.audit.writer.AuditType;
import org.bdware.doip.auditrepo.AutoAuditDO;
import org.bdware.doip.codec.doipMessage.DoipMessage;
import org.bdware.doip.encrypt.SM2Signer;
import org.bdware.doip.endpoint.client.ClientConfig;
import org.bdware.irp.stateinfo.StateInfoBase;
import org.bdware.sc.engine.JSONTool;


public class RepoProxy {
    private static final Logger LOGGER = LogManager.getLogger(RepoProxy.class);

    public static void main(String[] args) {
        LOGGER.info("abc");
    }

    static String prefix;
    public static String router;
    static EndpointConfig endpointConfig;

    public static void init(Object obj) {
        if (obj == null) {
            return;
        }
        if (obj instanceof String) {
            if (!((String) obj).startsWith("{")) {

            }
            TempConfigStorage storage = new TempConfigStorage((String) obj);
            endpointConfig = storage.loadAsEndpointConfig();
            prefix = storage.load().get("prefix").getAsString();
            router = storage.load().get("router").getAsString();
        } else {
            JsonElement je = JSONTool.convertMirrorToJson(obj);
            TempConfigStorage storage = new TempConfigStorage(je.toString());
            endpointConfig = storage.loadAsEndpointConfig();
            prefix = storage.load().get("prefix").getAsString();
            router = storage.load().get("router").getAsString();

        }
    }

    public static String getConfig() {
        return new Gson().toJson(endpointConfig);
    }

    public static String call() {
        return "hello..dafdskf";
    }

    public static Object getRepoStaticsMock(String repoDoid) {
        JsonObject result = new JsonObject();
        result.addProperty("doCount", 1234);
        result.addProperty("invokeCount", 5678);
        result.addProperty("doIndexCount", 1200);
        return JSONTool.convertJsonElementToMirror(result);
    }

    public static Object getRepoStatistics(String repoDoid) {
        JsonObject result = new JsonObject();
        try {
            DoipMessage helloMsg = getHelloMessage(repoDoid);
            JsonObject helloAttrs = helloMsg.header.parameters.attributes;
            result.add("doCount", getPropWithDefault(helloAttrs, "doCount", new JsonPrimitive(-1)));
            result.add("invokeCount", getPropWithDefault(helloAttrs, "invokeCount", new JsonPrimitive(-1)));
            result.add("doIndexCount", getPropWithDefault(helloAttrs, "doIndexCount", new JsonPrimitive(-1)));
            LOGGER.info(helloMsg);
            return JSONTool.convertJsonElementToMirror(result);
        } catch (Exception e) {
            result.addProperty("msg", e.getMessage());
        }
        result.addProperty("status", "offline");
        return JSONTool.convertJsonElementToMirror(result);
    }

    private static JsonElement getPropWithDefault(JsonObject jo, String attr, JsonPrimitive defaultValue) {
        if (jo != null && jo.has(attr))
            return jo.get(attr);
        return defaultValue;
    }

    private static DoipMessage getHelloMessage(String repoDoid) {
        try {
            AuditIrpClient irpClient = new AuditIrpClient(endpointConfig);
            AuditConfig auditConfig = irpClient.getAuditConfig();
            AuditDoipClient client = new AuditDoipClient(auditConfig, new SM2Signer(null));
            StateInfoBase stateInfoBase = irpClient.resolve(repoDoid);
            if (isDOIPRepo(stateInfoBase)) {
                ClientConfig config = new ClientConfig(stateInfoBase.getValues("address"));
                client.connect(config);
                return client.helloSync(repoDoid);
            }
        } catch (Exception e) {
        }
        return null;
    }

    //用于新增repo时判断它是否在线。
    //使用doip协议，发一个hello请求。
    public static Object pingRepo(String repoDoid) {
        JsonObject result = new JsonObject();
        try {
            if (getHelloMessage(repoDoid) != null) {
                result.addProperty("status", "online");
                return JSONTool.convertJsonElementToMirror(result);
            }
        } catch (Exception e) {
            result.addProperty("msg", e.getMessage());
        }
        result.addProperty("status", "offline");
        return JSONTool.convertJsonElementToMirror(result);
    }

    private static boolean isDOIPRepo(StateInfoBase base) {
        JsonObject handleValue = base.getHandleValues();
        return handleValue != null &&
                handleValue.has("protocol") &&
                handleValue.get("protocol").getAsString().equalsIgnoreCase("DOIP");

    }

    public static JsonElement getDoAuditRule(Object obj) {
        JsonObject jo = JSONTool.convertMirrorToJson(obj).getAsJsonObject();
        String doId = jo.get("doId").getAsString();
        if (!doId.contains("/")) {
            doId = prefix + "/" + doId;
        }
        ClientConfig config = null;
        AuditType type = null;
        try {
            AuditIrpClient irpClient = new AuditIrpClient(endpointConfig);
            AuditConfig auditConfig = irpClient.getAuditConfig();
            AuditDoipClient client = new AuditDoipClient(auditConfig, new SM2Signer(null));
            StateInfoBase result = irpClient.resolve(doId);
            config = new ClientConfig(result.getValues("address"));
            client.connect(config);
            DoipMessage msg = client.sendMessageSync(AutoAuditDO.getRepoAuditType(doId));
            type = AutoAuditDO.getAuditTypeFromRespMessage(msg);
            LOGGER.info(type);
        } catch (Exception e) {
            e.printStackTrace();
        }

        JsonObject ret = new JsonObject();
        ret.addProperty("total", 1);
        JsonArray jsonArray = new JsonArray();
        ret.add("data", jsonArray);
        String format = "{\"doId\":\"%s\",\"auditRule\":{\"type\":%d}}";
        if (type == null) {
            jsonArray.add(JsonParser.parseString(String.format(format, "不可配置：" + doId, 0)));
        } else
            jsonArray.add(JsonParser.parseString(String.format(format, doId, type.ordinal())));
        return ret;
    }

}