package org.bdware.sc.boundry.utils;

import org.bdware.sc.bean.ContractRequest;
import org.bdware.sc.boundry.JavaScriptEntry;
import org.bdware.sc.compiler.PermissionStub;
import org.bdware.sc.conn.ResultCallback;
import org.bdware.sc.conn.ServiceServer;
import org.bdware.sc.engine.DesktopEngine;
import org.bdware.sc.node.Permission;
import org.bdware.sc.util.JsonUtil;
import wrp.jdk.nashorn.internal.runtime.ScriptFunction;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.Timer;
import java.util.TimerTask;

@PermissionStub(permission = Permission.Async)
public class AsyncUtil {
    private static final Timer TIMER = new Timer();
//    public static ExecutorService executorService = Executors.newFixedThreadPool(10);

    public static String sleep(long sleep) {
        try {
            Thread.sleep(sleep);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "success";
    }

    public static String postFunction(final ScriptFunction callback, Object wrapper) {
        ServiceServer.executor.execute(
                () -> JavaScriptEntry.executeFunction(callback, wrapper));
        return "success";
    }

    public static TimerTask setTimeOut(
            final ScriptFunction callback, long delay, final Object arg) {
        TimerTask task =
                new TimerTask() {
                    @Override
                    public void run() {
                        JavaScriptEntry.executeFunction(callback, arg);
                    }
                };
        TIMER.schedule(task, delay);
        return task;
    }

    public static TimerTask setInterval(
            final ScriptFunction callback, long delay, long interval, final Object arg) {
        TimerTask task =
                new TimerTask() {
                    @Override
                    public void run() {
                        JavaScriptEntry.executeFunction(callback, arg);
                    }
                };
        TIMER.schedule(task, delay, interval);
        return task;
    }

    public static void executeContractAsyncWithoutSig(
            String contractID, String action, String arg, final ScriptFunction cb) {
        try {
            ContractRequest app = new ContractRequest();
            app.setContractID(contractID).setAction(action).setArg(arg);
            app.setRequestID((JavaScriptEntry.invokeID++) + "_" + JavaScriptEntry.random.nextInt());
            JavaScriptEntry.get.asyncGet(
                    "dd",
                    "executeContract",
                    JsonUtil.toJson(app),
                    new ResultCallback() {
                        @Override
                        public void onResult(String str) {
                            if (null != cb) {
                                DesktopEngine.applyWithGlobal(
                                        cb, JavaScriptEntry.currentEngine.getNashornGlobal(), str);
                            }
                        }
                    });
        } catch (Exception e) {
            ByteArrayOutputStream bo = new ByteArrayOutputStream();
            e.printStackTrace(new PrintStream(bo));
        }
    }
    public static String executeContractAsync(
            String contractID, String action, String arg, final ScriptFunction cb) {
        try {

            ContractRequest app = new ContractRequest();
            app.setContractID(contractID).setAction(action).setArg(arg);
            app.doSignature(JavaScriptEntry.getKeyPair());
            app.setRequestID((JavaScriptEntry.invokeID++) + "_" + JavaScriptEntry.random());
            app.setRequesterDOI(JavaScriptEntry.doi);
            JavaScriptEntry.get.asyncGet(
                    "dd",
                    "executeContract",
                    JsonUtil.toJson(app),
                    new ResultCallback() {
                        @Override
                        public void onResult(String str) {
                            if (cb != null) {
                                DesktopEngine.applyWithGlobal(
                                        cb, JavaScriptEntry.currentEngine.getNashornGlobal(), str, arg);
                            }
                        }
                    });
            return "success";
        } catch (Exception e) {
            ByteArrayOutputStream bo = new ByteArrayOutputStream();
            e.printStackTrace(new PrintStream(bo));
            return bo.toString();
        }
    }
}
