/*
 *   This file is a part of the SteamWar software.
 *
 *   Copyright (C) 2026 SteamWar.de-Serverteam
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU Affero General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *   GNU Affero General Public License for more details.
 *
 *   You should have received a copy of the GNU Affero General Public License
 *   along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

package de.steamwar;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * Parses Fabric-compatible .accesswidener files.
 * <p>
 * Supported format:
 * <pre>
 *   accessWidener v2 named
 *
 *   # comments are supported
 *   accessible class  net/minecraft/Foo
 *   accessible method net/minecraft/Foo someMethod ()V
 *   accessible field  net/minecraft/Foo someField I
 *   mutable    field  net/minecraft/Foo someField I
 *   extendable class  net/minecraft/Foo
 *   extendable method net/minecraft/Foo someMethod ()V
 *
 *   # transitive variants (expose widening to dependents)
 *   transitive-accessible class net/minecraft/Foo
 * </pre>
 */
public final class AccessWidenerParser {

    private AccessWidenerParser() {
    }

    public static List<AccessWidenerEntry> parse(InputStream in) throws IOException {
        List<AccessWidenerEntry> entries = new ArrayList<>();

        try (BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) {

            String line;
            boolean headerSeen = false;

            while ((line = reader.readLine()) != null) {
                // Strip inline comments
                int commentIdx = line.indexOf('#');
                if (commentIdx >= 0) line = line.substring(0, commentIdx);
                line = line.strip();

                if (line.isEmpty()) continue;

                if (!headerSeen) {
                    // First non-blank, non-comment line must be the header
                    if (!line.startsWith("accessWidener")) {
                        throw new IOException("Missing accessWidener header, got: " + line);
                    }
                    headerSeen = true;
                    continue;
                }

                AccessWidenerEntry entry = parseLine(line);
                if (entry != null) entries.add(entry);
            }
        }

        return entries;
    }

    private static AccessWidenerEntry parseLine(String line) {
        String[] parts = line.split("\\s+");
        if (parts.length < 3) return null;

        String directive = parts[0]; // accessible / mutable / extendable / transitive-*
        String memberType = parts[1]; // class / method / field
        String target = parts[2]; // internal class name

        return switch (memberType) {
            case "class" -> new AccessWidenerEntry(directive, "class", target, null, null);
            case "method", "field" -> {
                if (parts.length < 5) yield null;
                yield new AccessWidenerEntry(directive, memberType, target, parts[3], parts[4]);
            }
            default -> null;
        };
    }
}