package de.accso.flexinale.common.api.event;

import de.accso.flexinale.common.shared_kernel.Identifiable;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

import java.util.ArrayList;
import java.util.List;

@SuppressWarnings("unused")
public class EventContext {
    public record EventHistoryElement(Identifiable.Id id, Class<? extends Event> eventType) {}

    public Identifiable.Id correlationId;

    public List<EventHistoryElement> eventHistory;

    private EventContext() {} // used by Jackson deserialization

    public EventContext(final Identifiable.Id correlationId, final List<EventHistoryElement> eventHistory) {
        this.correlationId = correlationId;
        this.eventHistory = List.copyOf(eventHistory);
    }

    public EventContext(final Identifiable.Id correlationId,
                 final List<EventHistoryElement> eventHistory, final EventHistoryElement additionalHistoryElement) {
        this.correlationId = correlationId;

        // pretty ugly to copy plus add to immutable list
        List<EventHistoryElement> tempList = new ArrayList<>(eventHistory);
        tempList.add(additionalHistoryElement);
        this.eventHistory = List.copyOf(tempList);
    }

    public boolean equalsByCorrelationId(EventContext that) {
        return this.correlationId.equals(that.correlationId);
    }

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
    }

    @Override
    public boolean equals(final Object o) {
        if (this == o) {return true;}

        if (o == null || getClass() != o.getClass()) {return false;}

        EventContext that = (EventContext) o;

        return new EqualsBuilder()
                .append(eventHistory, that.eventHistory)
                .isEquals();
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder(17, 37)
                .append(this.correlationId)
                .toHashCode();
    }
}