package org.bdware.sc.memory;

import org.bdware.sc.boundry.JavaScriptEntry;
import org.bdware.sc.boundry.Resources;
import org.bdware.sc.util.JsonUtil;
import wrp.jdk.nashorn.api.scripting.NashornScriptEngine;
import wrp.jdk.nashorn.api.scripting.ScriptObjectMirror;

import javax.script.Bindings;
import javax.script.Invocable;
import javax.script.ScriptContext;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.Map;
import java.util.Random;
import java.util.zip.GZIPInputStream;

public class MemoryRecoverUtil {
    NashornScriptEngine engine;
    String loadContent;
    MemoryDump memoryDump = null;
    Resources resource;

    public MemoryRecoverUtil(NashornScriptEngine en, Resources r) {
        this.engine = en;
        this.resource = r;
    }

    //支持传入memory文件路径或者直接是memory的字符串
    public void loadMemory(String path, boolean stateful) {
        synchronized (engine) {
            File file = new File(path);
            try {
                if (file.exists()) {
                    try {
                        FileInputStream fileout = new FileInputStream(file);
                        GZIPInputStream gzin = new GZIPInputStream(fileout);
                        ObjectInputStream reader = new ObjectInputStream(gzin);

//                        MemoryDump temp = new MemoryDump();
//                        temp.objects = (Map<Long, MemoryObject>) reader.readObject();
//                        String content = JsonUtil.toPrettyJson(temp);

                        MemoryDump temp = (MemoryDump) reader.readObject();
                        String content = JsonUtil.toPrettyJson(temp.objects);
                        temp.jseDump.printContent();
                        long invokeID = temp.jseDump.invokeID;
                        int copies = temp.jseDump.numsOfCopies;
                        long formerInvokeID = JavaScriptEntry.invokeID;
                        JavaScriptEntry.invokeID = invokeID;
                        JavaScriptEntry.numOfCopies = copies;
                        if (JavaScriptEntry.random == null) {
                            JavaScriptEntry.random = new Random();
                            JavaScriptEntry.random.setSeed(temp.jseDump.ranSeed);
                        }
                        if (formerInvokeID > invokeID) {
                            JavaScriptEntry.random = new Random();
                            JavaScriptEntry.random.setSeed(temp.jseDump.ranSeed);
                            for (long i = 0; i < invokeID; i++) {
                                JavaScriptEntry.random.nextInt();
                            }
                        } else {
                            for (long i = formerInvokeID; i < invokeID; i++) {
                                JavaScriptEntry.random.nextInt();
                            }
                        }

                        //memoryDump = MemoryDump.loadFromStr(content);
                        if (stateful) {
                            memoryDump = temp;
                        }
                        reader.close();
                    } catch (IOException | ClassNotFoundException e) {
                        e.printStackTrace();
                    }
                } else {  //直接传入的是字符串
                    String[] strs = path.split("--seperate--");
                    String content = strs[0];
                    String jse = strs[1];
                    System.out.println("MemoryRecover从字符串load:\n" + content + "\n" + jse);
                    String strs2[] = jse.split(";");
                    long invokeID = Long.parseLong(strs2[0]);
                    int copies = Integer.parseInt(strs2[2]);
                    long formerInvokeID = JavaScriptEntry.invokeID;
                    String contractID = strs2[1];
                    JavaScriptEntry.invokeID = invokeID;
                    JavaScriptEntry.numOfCopies = copies;
                    if (JavaScriptEntry.random == null) {
                        JavaScriptEntry.random = new Random();
                        JavaScriptEntry.random.setSeed(Integer.valueOf(contractID));
                    }
                    if (formerInvokeID > invokeID) {
                        JavaScriptEntry.random = new Random();
                        JavaScriptEntry.random.setSeed(Integer.valueOf(contractID));
                        for (long i = 0; i < invokeID; i++) {
                            JavaScriptEntry.random.nextInt();
                        }
                    } else {
                        for (long i = formerInvokeID; i < invokeID; i++) {
                            JavaScriptEntry.random.nextInt();
                        }
                    }

                    if (stateful) { //有状态合约
                        memoryDump = MemoryDump.loadFromStr(content);
                    }
                }

                if (stateful) {
                    MemoryJSObject root = memoryDump.getRoot();
                    Map<Long, Object> objects = memoryDump.recreateObject();
                    ScriptObjectMirror global = (ScriptObjectMirror) objects.get(0L);
                    Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);
                    for (Object key : global.keySet()) {
                        if (global.get(key) != null) bindings.put((String) key, global.get(key));
                    }
                }
                this.memoryDump = null;
                if (resource != null)
                    ((Invocable) engine).invokeFunction("defineProp", "Resources", resource);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /*
    public void loadMemory(String path) {
    	try {
    		String memory;
    		File mem = new File(path);
    		FileInputStream fileout = new FileInputStream(mem);
    		ObjectInputStream reader = new ObjectInputStream(fileout);
    		loadContent = (String) reader.readObject();
    		// System.out.println("[MemoryRecoverUtil] loadContent : \n" + loadContent);
    		reader.close();
    		memoryDump = MemoryDump.loadFromStr(loadContent);


    		String ret = JsonUtil.toPrettyJson(memoryDump);
    		MemoryJSObject root = memoryDump.getRoot();
    		Map<Long, Object> objects = memoryDump.recreateObject();
    		ScriptObjectMirror global = (ScriptObjectMirror) objects.get(0L);
    		Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);
    		for (Object key : global.keySet()) {
    			if (global.get(key) != null)
    				bindings.put((String) key, global.get(key));
    		}
    		this.memoryDump = null;
    		if (resource != null)
    			((Invocable) engine).invokeFunction("defineProp", "Resources", resource);
    	} catch (Exception e) {
    		// TODO Auto-generated catch block
    		e.printStackTrace();
    	}
    }
    */
}
