package com.icomsys.main_vm.biz.common.common.service.functionnode;

import com.icomsys.main_vm.biz.common.common.service.functionnode.ex.WsNotAvailableException;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class FunctionWsNashorn {

    /**
     * @Name 펑션노드
     * @Description 펀션노드 스크립트엔진
     * @Author JangWonSeok
     * @CreateDate 2023. 03. 09.
     * varList: functionNode 의 fParam[0], fParam[1] 값을 받는곳
     * callData: 콜봇이 유지하고있는 데이터
     * initSctipt: 자바스크립트
     */

    private List<String> varList;
    private HashMap callData = new HashMap<>();
    private String initSctipt;
    private List<String> reservesWord = Arrays.asList("while", "sleep", "timeout", "interval", "$(");

    public static FunctionWsNashorn builder(int timeMilli) throws ExecutionException, InterruptedException, TimeoutException {
        int time = 5000;
        if (timeMilli > 0 && timeMilli < time) time = timeMilli;
        return Executors.newSingleThreadExecutor().submit(FunctionWsNashorn::new).get(time, TimeUnit.MILLISECONDS);
    }

    public FunctionWsNashorn create(FunctionVo dto) {
        if (dto.getInitSctipt().length() < 5) throw new WsNotAvailableException("코드길이가 너무 적습니다.");
        if (dto.getVarList().size() < 1) throw new WsNotAvailableException("파라미터가 없습니다.");
        if (dto.getCallData().size() < 1) throw new WsNotAvailableException("콜데이터가 없습니다.");
        this.varList = dto.getVarList();
        this.initSctipt = dto.getInitSctipt();
        this.callData = dto.getCallData();
        return this;
    }

    public Map build() throws ScriptException {
        ScriptEngine se = new ScriptEngineManager().getEngineByName("nashorn");
        for (String e : varList) {
            if (callData.containsKey(e)) {
                se.put(e, callData.get(e));
            } else {
                se.put(e, "");
            }
        }
        se.eval(this.initSctipt);
        for (String e : varList) {
            callData.put(e, se.get(e));
        }
        return this.callData;
    }

    public FunctionWsNashorn noTag() {
        if (this.initSctipt.matches("<.+?>")) throw new WsNotAvailableException("HTML TAG는 입력 할 수 없습니다.");
        return this;
    }

    public FunctionWsNashorn CheckBlackList() {
        String copy = this.initSctipt;
        for (String e : reservesWord) {
            if (copy.toLowerCase().contains(e)) throw new WsNotAvailableException("JAVASCRIPT만 사용해주세요.");
        }
        return this;
    }

}
