package org.bdware.sc.redo;

import com.google.gson.JsonElement;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bdware.sc.ContractResult;
import org.bdware.sc.bean.ContractRequest;
import org.bdware.sc.engine.DesktopEngine;
import org.bdware.sc.util.JsonUtil;

import java.io.*;
import java.util.ArrayList;

public class TransRecoverUtil {
    private static final Logger LOGGER = LogManager.getLogger(TransRecoverUtil.class);
    public ArrayList<TransRecord> transRecords;
    public TransRecord curRecoverRecord;
    DesktopEngine engine;

    public TransRecoverUtil(DesktopEngine en) {
        this.engine = en;
        transRecords = new ArrayList<TransRecord>();
    }

    public void setTraceRecords(String fileName) {
        TransRecord cur_read = null;
        File file = new File(fileName);

        try {
            FileReader fr = new FileReader(file);
            BufferedReader br = new BufferedReader(fr);
            String line = "";
            String[] arrs = null;
            while ((line = br.readLine()) != null) {
                String[] strs = line.split(";");
                String arg;
                if (strs.length < 5) {   //调用记录参数为空
                    arg = null;
                } else {
                    arg = strs[4];
                }

                if (strs[0].equals("===TransRecord===")) {
                    if (cur_read != null) {
                        transRecords.add(cur_read);
                        System.out.println("恢复时加入 " + cur_read.toString());
                    }
                    if (strs[1].equals("true"))
                        cur_read = new TransRecord(strs[3], JsonUtil.parseString(arg), Integer.parseInt(strs[2]));
                    else
                        cur_read = new TransRecord(strs[3], JsonUtil.parseString(arg));
                } else {
                    cur_read.addExecutes(strs[0], strs[1]);
                }
            }
            if (cur_read != null) {
                transRecords.add(cur_read);
                System.out.println("恢复时加入 " + cur_read.toString());
            }
            br.close();
            fr.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void recoverFromTransRecord() {
        synchronized (engine) {
            engine.setRecovering(true);
            for (int i = 0; i < transRecords.size(); i++) {
                curRecoverRecord = transRecords.get(i);
                String funName = curRecoverRecord.getFuncName();
                JsonElement arg = curRecoverRecord.getArg();

                ContractRequest ac = null;
                ac = new ContractRequest();
                ac.setAction(funName);
                ac.setArg(arg);
                ac.needSeq = curRecoverRecord.needSeq;
                if (ac.needSeq) {
                    ac.seq = curRecoverRecord.seq;
                    LOGGER.info("[TransRecordUtil]  redo 重新执行事务 " + ac.seq);
                }
                System.out.println("[TransRecoverUtil] recover " + ac.needSeq + " " + ac.seq + "  " + ac.getAction() + " " + ac.getArg());

                ContractResult result = engine.executeContract(ac);

                if (result.status != ContractResult.Status.Success) {
                    System.out.println("[错误]" + result.status);
                }
            }
            engine.setRecovering(false);
        }
    }

    //TODO
    public void recoverFromATransRecord(TransRecord record) {

    }
}