package me.astro.modengine.script;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Requirer {
    public static String compile(String src) {
        final String[] callbackNames = "attackHook;chatHook;continueDestroyBlock;destroyBlock;projectileHitEntityHook;eatHook;entityAddedHook;entityHurtHook;entityRemovedHook;explodeHook;serverMessageReceiveHook;deathHook;playerAddExpHook;playerExpLevelChangeHook;redstoneUpdateHook;newLevel;startDestroyBlock;projectileHitBlockHook;modTick;useItem".split(";");
        final Pattern linePattern = Pattern.compile("require\\s\"\\w+(\\.(mod_engine|js))?\";?");
        final Pattern scriptPattern = Pattern.compile("\"\\w+(\\.(mod_engine|js))?");

        ArrayList<String> scriptNames = new ArrayList<>();
        String requiredSource = "";
        Matcher lineMatcher = linePattern.matcher(src);

        while (lineMatcher.find()) {
            Matcher scriptMatcher = scriptPattern.matcher(lineMatcher.group());
            if (scriptMatcher.find()) {
                scriptNames.add(scriptMatcher.group().substring(1));
                src = src.substring(0, lineMatcher.start()) + src.substring(lineMatcher.end());
            }
        }

        for (String name : scriptNames) {
            if (!name.endsWith(".mod_engine") && !name.endsWith(".js")) {
                name += ".js";
            }

            File scriptFile = new File(ScriptManager.SCRIPT_PATH, name);
            if (scriptFile.exists()) {
                Script script = new Script(scriptFile.getPath());
                requiredSource += script.getSource();
            }
        }

        for (String name : callbackNames) {
            Pattern pattern = Pattern.compile("function\\s" + name + "\\s*\\(");
            Matcher matcher = pattern.matcher(src);
            ArrayList<String> funcList = new ArrayList<>();
            while (matcher.find()) {
                int bracketCnt = 1;
                int charCnt = 0;
                String str = src.substring(matcher.end());
                int start = str.indexOf("{") + 1;
                str = str.substring(start);
                for (int i = 0, len = str.length(); i < len && bracketCnt > 0; i++) {
                    String cr = String.valueOf(str.charAt(i));
                    if (cr.equals("{")) {
                        bracketCnt++;
                    } else if (cr.equals("}")) {
                        bracketCnt--;
                    }
                    charCnt++;
                }
                if (bracketCnt == 0) {
                    String funcStr = str.substring(0, charCnt - 1);
                    funcList.add(funcStr);
                    src = src.substring(0, matcher.start()) + src.substring(start + matcher.end() + charCnt);
                    matcher = pattern.matcher(src);
                }
            }
            if (!funcList.isEmpty()) {
                String[] arr = new String[funcList.size()];
                arr = funcList.toArray(arr);
                String src_ = Arrays.toString(arr);
                src_ = src_.substring(1, src_.length() - 1).replaceAll(", ", "");
                src += "function " + name + "(" + "" + ") {" + src_ + "}";
            }
        }

        return requiredSource + src.replace("/\n{3,}/", "");
    }
}
