package org.bdware.analysis.dynamic;

import com.google.gson.JsonObject;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bdware.sc.util.JsonUtil;

import java.io.InputStream;
import java.util.*;

public class ProgramPoint {
    private static final Logger LOGGER = LogManager.getLogger(ProgramPoint.class);
    List<Transaction> trans;
    List<FunctionTx> functionTrans;

    public ProgramPoint(InputStream in) {
        Scanner sc = new Scanner(in);
        trans = new ArrayList<>();
        functionTrans = new ArrayList<>();
        Transaction transaction = new Transaction();
        FunctionTx funcTx = new FunctionTx();
        transaction.tmToVal = new HashMap<>();
        funcTx.ppToVal = new HashMap<>();
        // TODO ignore handle transaction start
        // TODO ignore handle contractID/method....
        // TODO ignore handle transaction end
        while (sc.hasNextLine()) {
            String string = sc.nextLine().replace("[ProgramPointCounter]", "");
            LOGGER.debug("[string: ]" + string);
            if (string.contains("ENTER")) {
                String[] strings = string.split("_");
                strings = strings[1].split("[(]");
                System.out.println("[stringsss: ]" + strings[0]);
                funcTx.insert(strings[0], "ENTER");
            }
            //			if (string.contains("EXIT")) {
            //				String[] strings = string.split("_");
            //				strings=strings[1].split("-");
            //				System.out.println("[stringsss: ]" + strings[0]);
            //				functionMap.put(strings[1], "EXIT");
            //			}
            if (string.contains("traceMark")) {
                JsonObject jo = JsonUtil.parseStringAsJsonObject(string);
                if (jo.get("traceMark") != null) {
                    if (jo.get("lval") != null) {
                        transaction.insert(
                                jo.get("traceMark").getAsInt(), jo.get("lval").getAsInt());
                        transaction.insert(
                                jo.get("traceMark").getAsInt(), jo.get("rval").getAsInt());
                    } else {
                        transaction.insert(
                                jo.get("traceMark").getAsInt(), jo.get("val").getAsInt());
                    }
                }
            }
        }
        LOGGER.info(funcTx.ppToVal);
        LOGGER.info(transaction.tmToVal);
        sc.close();
    }

    static class Transaction {
        Map<Integer, List<Integer>> tmToVal;

        public void insert(int traceMark, int val) {
            List<Integer> ret;
            if (!tmToVal.containsKey(traceMark)) {
                ret = new ArrayList<>();
                tmToVal.put(traceMark, ret);
            } else {
                ret = tmToVal.get(traceMark);
            }
            ret.add(val);
        }
    }

    static class FunctionTx {
        Map<String, List<String>> ppToVal;

        public void insert(String functionID, String val) {
            List<String> ret;
            if (!ppToVal.containsKey(functionID)) {
                ret = new ArrayList<>();
                ppToVal.put(functionID, ret);
            } else {
                ret = ppToVal.get(functionID);
            }
            ret.add(val);
        }
    }
}
