package ru.yandex.qe.dispenser.domain;

import java.math.BigDecimal;
import java.util.Objects;
import java.util.Set;

import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;

@ParametersAreNonnullByDefault
public class QuotaRequestChangeBuilder {
    @Nullable
    private Long id;
    @Nullable
    private QuotaChangeRequest.ChangeKey changeKey;
    @Nullable
    private QuotaChangeRequest.BigOrder bigOrder;
    @Nullable
    private Resource resource;
    @Nullable
    private Set<Segment> segments;
    @Nullable
    private Long amount;
    @Nullable
    private Long amountReady;
    @Nullable
    private Long amountAllocated;
    @Nullable
    private Long amountAllocating;
    @Nullable
    private BigDecimal owningCost;

    QuotaRequestChangeBuilder() {
    }

    public QuotaRequestChangeBuilder id(final long id) {
        this.id = id;
        return this;
    }

    public QuotaRequestChangeBuilder key(final QuotaChangeRequest.ChangeKey key) {
        changeKey = key;
        resource = key.getResource();
        segments = key.getSegments();
        bigOrder = key.getBigOrder();
        return this;
    }

    public QuotaRequestChangeBuilder key(final Quota.Key key) {
        changeKey = null;
        resource = key.getSpec().getResource();
        segments = key.getSegments();
        return this;
    }

    public QuotaRequestChangeBuilder resource(final Resource resource) {
        changeKey = null;
        this.resource = resource;
        return this;
    }

    public QuotaRequestChangeBuilder order(@Nullable final QuotaChangeRequest.BigOrder bigOrder) {
        changeKey = null;
        this.bigOrder = bigOrder;
        return this;
    }

    public QuotaRequestChangeBuilder order(final Campaign.BigOrder bigOrder) {
        return order(new QuotaChangeRequest.BigOrder(bigOrder.getBigOrderId(), bigOrder.getDate(), true));
    }

    public QuotaRequestChangeBuilder segments(final Set<Segment> segments) {
        changeKey = null;
        this.segments = segments;
        return this;
    }

    public QuotaRequestChangeBuilder amount(final long amount) {
        this.amount = amount;
        return this;
    }

    public QuotaRequestChangeBuilder amountReady(final long amount) {
        this.amountReady = amount;
        return this;
    }

    public QuotaRequestChangeBuilder amountAllocated(final long amount) {
        this.amountAllocated = amount;
        return this;
    }

    public QuotaRequestChangeBuilder amountAllocating(final long amountAllocating) {
        this.amountAllocating = amountAllocating;
        return this;
    }

    public QuotaRequestChangeBuilder owningCost(final BigDecimal owningCost) {
        this.owningCost = owningCost;
        return this;
    }

    public QuotaChangeRequest.Change build() {
        if (changeKey == null) {
            changeKey = new QuotaChangeRequest.ChangeKey(
                    bigOrder,
                    Objects.requireNonNull(resource, "Resource or change key required for request change"),
                    Objects.requireNonNull(segments, "Segments or change key required for request change")
            );
        }
        final QuotaChangeRequest.Change change = new QuotaChangeRequest.Change(
                changeKey,
                Objects.requireNonNull(amount, "Amount required for request change"),
                Objects.requireNonNull(amountReady, "Amount ready required for request change"),
                Objects.requireNonNull(amountAllocated, "Amount allocated required for request change"),
                Objects.requireNonNull(amountAllocating, "Amount allocating required for request change"),
                Objects.requireNonNull(owningCost, "Owning cost required for request change")
        );
        if (id != null) {
            change.setId(id);
        }
        return change;
    }
}
