package org.cqback.runtime.event;

import org.cqback.actor.ActorId;
import org.cqback.api.aggregate.Aggregate;
import org.cqback.api.aggregate.AggregateActorRole;
import org.cqback.api.aggregate.TransientAggregate;
import org.cqback.api.event.AggregateEvent;

import java.util.Date;
import java.util.Map;
import java.util.UUID;

/**
 * Created by pragone
 * Created on 30/12/2015 at 10:20 AM
 *
 * @author Paolo Ragone <pragone@ebay.com>
 */
public abstract class AggregateCreatingEvent implements AggregateEvent {
    private final ActorId actorId;
    private final String aggregateType;
    private final UUID aggregateId;
    private final Map<String, Object> initialAttributes;
    private final Date creationDate;

    protected AggregateCreatingEvent(ActorId actorId, String aggregateType, UUID aggregateId, Map<String,Object> initialAttributes, Date creationDate) {
        this.actorId = actorId;
        this.aggregateType = aggregateType;
        this.aggregateId = aggregateId;
        this.initialAttributes = initialAttributes;
        this.creationDate = creationDate;
    }

    protected AggregateCreatingEvent(ActorId actorId, String aggregateType, UUID aggregateId, Map<String,Object> initialAttributes) {
        this(actorId, aggregateType, aggregateId, initialAttributes, new Date());
    }

    @Override
    public void apply(Aggregate aggregate) {
        if (!(aggregate instanceof TransientAggregate)) {
            throw new IllegalArgumentException(getClass().getSimpleName() + " events can only be applied to " + TransientAggregate.class.getSimpleName() + " aggregates");
        }
        ((TransientAggregate) aggregate).setCreationDate(creationDate);
        ((TransientAggregate) aggregate).setAggregateType(aggregateType);
        aggregate.addActor(AggregateActorRole.CREATOR, actorId);
        if (initialAttributes != null) {
            aggregate.addAllAttributes(initialAttributes);
        }
        this.doApply(aggregate);
    }

    public String getAggregateType() {
        return aggregateType;
    }

    protected abstract void doApply(Aggregate aggregate);

    @Override
    public UUID getAggregateId() {
        return aggregateId;
    }

    public Date getCreationDate() {
        return creationDate;
    }
}
