// • ▌ ▄ ·.  ▄▄▄·  ▄▄ • ▪   ▄▄· ▄▄▄▄·  ▄▄▄·  ▐▄▄▄  ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀  █▪▀▀▀ ▀  ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀  ▀  ▀ ▀▀  █▪ ▀▀▀
//      Magicbane Emulator Project © 2013 - 2024
//                www.magicbane.com

package engine.wpak;

import engine.gameManager.ConfigManager;
import engine.mbEnums;
import engine.wpak.data.PowerAction;
import engine.wpak.data.PowerData;
import engine.wpak.data.PowerEntry;
import org.pmw.tinylog.Logger;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class PowersParser {

    public static String powersPath = ConfigManager.DEFAULT_DATA_DIR + "wpak/Powers.cfg";
    private static final Pattern POWER_REGEX = Pattern.compile("(?<=POWERBEGIN)(.+?)(?=POWEREND)", Pattern.DOTALL);
    private static final Pattern STRSPLIT_REGEX = Pattern.compile("([^\"]\\S*|\"[^\"]*\")\\s*");

    public static void parseWpakFile() throws IOException {

        // Read .wpak file from disk

        byte[] fileData = Files.readAllBytes(Paths.get(powersPath));
        String fileContents = new String(fileData);

        // Iterate over power entries from .wpak data

        Matcher matcher = POWER_REGEX.matcher(fileContents);

        while (matcher.find()) {

            PowerEntry powerEntry = parsePowerEntry(matcher.group().trim());

        }
    }

    private static PowerEntry parsePowerEntry(String powerData) {

        PowerEntry powerEntry = new PowerEntry();

        try {

            String[] lineData = powerData.trim().split("\n");
            ArrayList<String> powerHeader = new ArrayList<>();

            // Parse header

            String headerString = lineData[0];
            headerString = headerString.replace("\n", " ");

            Matcher matcher = STRSPLIT_REGEX.matcher(headerString);

            while (matcher.find())
                powerHeader.add(matcher.group().trim());

            java.util.Iterator<String> iterator = powerHeader.iterator();

            powerEntry.power_id = iterator.next();
            powerEntry.power = iterator.next().replaceAll("\"", "");

            PowerData power = new PowerData();
            power.power_type = mbEnums.PowerType.valueOf(iterator.next());
            power.icon = Integer.parseInt(iterator.next());
            power.powerBase = iterator.next().replaceAll("\"", "");
            powerEntry.powers.add(power);

            String nextValue = iterator.next();

            // Account for second definition

            if (nextValue.equals("SPELL") || nextValue.equals("SKILL")) {
                power = new PowerData();
                power.power_type = mbEnums.PowerType.valueOf(nextValue);
                power.icon = Integer.parseInt(iterator.next());
                power.powerBase = iterator.next().replaceAll("\"", "");
                powerEntry.powers.add(power);
                powerEntry.target_type = mbEnums.PowerTargetType.valueOf(iterator.next());
            } else
                powerEntry.target_type = mbEnums.PowerTargetType.valueOf(nextValue);

            powerEntry.range = Integer.parseInt(iterator.next());
            powerEntry.areaType = mbEnums.AreaType.valueOf(iterator.next());
            powerEntry.areaRange = Integer.parseInt(iterator.next());
            powerEntry.excludeType = mbEnums.ExcludeType.valueOf(iterator.next());
            powerEntry.costType = mbEnums.CostType.valueOf(iterator.next());
            powerEntry.cost = Float.parseFloat(iterator.next());
            powerEntry.difficulty = Float.parseFloat(iterator.next());
            powerEntry.precision = Float.parseFloat(iterator.next());
            powerEntry.init_time = Float.parseFloat(iterator.next().replaceAll("(\\.0)+$", ""));
            powerEntry.release_time = Float.parseFloat(iterator.next());
            powerEntry.recycle_time = Float.parseFloat(iterator.next());
            powerEntry.hitRollYN = Integer.parseInt(iterator.next());
            powerEntry.castingMode = mbEnums.CastingModeType.valueOf(iterator.next());
            powerEntry.initAmin = Integer.parseInt(iterator.next());
            powerEntry.releaseAnim = Integer.parseInt(iterator.next());
            powerEntry.targetSelect = mbEnums.TargetSelectType.valueOf(iterator.next());

            // Process key value pairs after header

            iterator = Arrays.stream(lineData).iterator();
            iterator.next(); // Ignore header

            while (iterator.hasNext()) {

                String lineValue = iterator.next();
                String[] lineValues = lineValue.split("=");
                String key = lineValues[0].trim();
                PowerAction powerAction;
                String[] arguments;

                switch (key) {
                    case "ACTION":
                        powerAction = new PowerAction();
                        arguments = lineValues[1].trim().split(" ");
                        powerAction.effect_id = arguments[0];
                        powerAction.minTrains = Integer.parseInt(arguments[1]);
                        powerAction.maxTrains = Integer.parseInt(arguments[2]);
                        powerAction.duration = Integer.parseInt(arguments[3]);
                        powerAction.curve = mbEnums.CompoundCurveType.valueOf(arguments[4]);
                        powerAction.stackingCategory = arguments[5];
                        powerAction.stackingPriority = Integer.parseInt(arguments[6]);
                        powerAction.categoryToPower = mbEnums.CategoryToPowerType.valueOf(arguments[7]);
                        powerEntry.actions.add(powerAction);
                        break;
                    case "MaLevel":
                        powerEntry.maxLevel = Integer.parseInt(lineValues[1].trim());
                        break;
                    default:
                        Logger.error("Unhandled variable type:" + key);
                }
            }

        } catch (Exception e) {
            Logger.error(powerEntry.power_id);
        }

        return powerEntry;
    }

}