package p.studio.compiler.source.diagnostics;

import lombok.Getter;
import p.studio.compiler.source.Span;
import p.studio.utilities.structures.ReadOnlyList;

import java.util.List;
import java.util.Map;
import java.util.Objects;

@Getter
public class Diagnostic {
    private final Severity severity;
    private final String code;
    private final DiagnosticPhase phase;
    private final String templateId;
    private final Map<String, String> placeholders;
    private final String message;
    private final Span span;
    private final ReadOnlyList<RelatedSpan> related;

    public Diagnostic(
            final Severity severity,
            final String code,
            final String message,
            final Span span,
            final List<RelatedSpan> related) {
        this(
                severity,
                code,
                DiagnosticPhase.fromCode(code),
                code,
                Map.of(),
                message,
                span,
                related);
    }

    public Diagnostic(
            final Severity severity,
            final String code,
            final DiagnosticPhase phase,
            final String templateId,
            final Map<String, String> placeholders,
            final String message,
            final Span span,
            final List<RelatedSpan> related) {
        this.severity = Objects.requireNonNull(severity);
        this.code = Objects.requireNonNull(code);
        this.phase = Objects.requireNonNull(phase);
        this.templateId = Objects.requireNonNull(templateId);
        this.placeholders = Map.copyOf(Objects.requireNonNull(placeholders));
        this.message = Objects.requireNonNull(message);
        this.span = Objects.requireNonNull(span);
        this.related = ReadOnlyList.wrap(List.copyOf(Objects.requireNonNull(related)));
    }

    @Override
    public String toString() {
        return "%s[%s:%s] %s @ %s".formatted(
                severity,
                phase.id(),
                code,
                message,
                span);
    }
}
