package p.studio.compiler.models;

import p.studio.compiler.source.identifiers.FileId;
import p.studio.compiler.source.tables.CallableSignatureRef;
import p.studio.compiler.source.tables.IntrinsicReference;
import p.studio.compiler.source.tables.ModuleReference;
import p.studio.utilities.structures.ReadOnlyList;

import java.util.Objects;

public record IRBackendFile(
        FileId fileId,
        ReadOnlyList<IRFunction> functions,
        ReadOnlyList<IRSyntheticFunction> syntheticFunctions,
        ReadOnlyList<IRGlobal> globals,
        ReadOnlyList<IRBackendExecutableFunction> executableFunctions,
        IRReservedMetadata reservedMetadata,
        ReadOnlyList<ModuleReference> modulePool,
        ReadOnlyList<CallableSignatureRef> callableSignatures,
        ReadOnlyList<IntrinsicReference> intrinsicPool) {
    public IRBackendFile {
        fileId = Objects.requireNonNull(fileId, "fileId");
        functions = functions == null ? ReadOnlyList.empty() : functions;
        syntheticFunctions = syntheticFunctions == null ? ReadOnlyList.empty() : syntheticFunctions;
        globals = globals == null ? ReadOnlyList.empty() : globals;
        executableFunctions = executableFunctions == null ? ReadOnlyList.empty() : executableFunctions;
        reservedMetadata = reservedMetadata == null ? IRReservedMetadata.empty() : reservedMetadata;
        modulePool = modulePool == null ? ReadOnlyList.empty() : modulePool;
        callableSignatures = callableSignatures == null ? ReadOnlyList.empty() : callableSignatures;
        intrinsicPool = intrinsicPool == null ? ReadOnlyList.empty() : intrinsicPool;
    }

    public IRBackendFile(
            final FileId fileId,
            final ReadOnlyList<IRFunction> functions) {
        this(
                fileId,
                functions,
                ReadOnlyList.empty(),
                ReadOnlyList.empty(),
                ReadOnlyList.empty(),
                IRReservedMetadata.empty(),
                ReadOnlyList.empty(),
                ReadOnlyList.empty(),
                ReadOnlyList.empty());
    }

    public static IRBackendFile empty(final FileId fileId) {
        return new IRBackendFile(
                fileId,
                ReadOnlyList.empty(),
                ReadOnlyList.empty(),
                ReadOnlyList.empty(),
                ReadOnlyList.empty(),
                IRReservedMetadata.empty(),
                ReadOnlyList.empty(),
                ReadOnlyList.empty(),
                ReadOnlyList.empty());
    }

    public IRBackendFile(
            final FileId fileId,
            final ReadOnlyList<IRFunction> functions,
            final IRReservedMetadata reservedMetadata) {
        this(
                fileId,
                functions,
                ReadOnlyList.empty(),
                ReadOnlyList.empty(),
                ReadOnlyList.empty(),
                reservedMetadata,
                ReadOnlyList.empty(),
                ReadOnlyList.empty(),
                ReadOnlyList.empty());
    }

    public IRBackendFile(
            final FileId fileId,
            final ReadOnlyList<IRFunction> functions,
            final ReadOnlyList<IRBackendExecutableFunction> executableFunctions,
            final IRReservedMetadata reservedMetadata,
            final ReadOnlyList<CallableSignatureRef> callableSignatures,
            final ReadOnlyList<IntrinsicReference> intrinsicPool) {
        this(
                fileId,
                functions,
                ReadOnlyList.empty(),
                ReadOnlyList.empty(),
                executableFunctions,
                reservedMetadata,
                ReadOnlyList.empty(),
                callableSignatures,
                intrinsicPool);
    }

    public IRBackendFile(
            final FileId fileId,
            final ReadOnlyList<IRFunction> functions,
            final ReadOnlyList<IRBackendExecutableFunction> executableFunctions,
            final IRReservedMetadata reservedMetadata,
            final ReadOnlyList<ModuleReference> modulePool,
            final ReadOnlyList<CallableSignatureRef> callableSignatures,
            final ReadOnlyList<IntrinsicReference> intrinsicPool) {
        this(
                fileId,
                functions,
                ReadOnlyList.empty(),
                ReadOnlyList.empty(),
                executableFunctions,
                reservedMetadata,
                modulePool,
                callableSignatures,
                intrinsicPool);
    }
}
