package ru.yandex.qe.dispenser.ws.quota.request.owning_cost;

import java.util.List;
import java.util.Objects;
import java.util.Optional;

import org.jetbrains.annotations.Nullable;

/**
 * General context for owning cost calculation.
 *
 * @author Ruslan Kadriev <aqru@yandex-team.ru>
 */
public class QuotaChangeRequestOwningCostContext {
    private final List<ChangeOwningCostContext> changeOwningCostContexts;
    @Nullable
    private final List<ChangeOwningCostContext> originalChangeOwningCostContexts;
    private final Mode mode;

    private QuotaChangeRequestOwningCostContext(List<ChangeOwningCostContext> changeOwningCostContexts,
                                                @Nullable List<ChangeOwningCostContext> originalChangeOwningCostContexts,
                                                Mode mode) {
        this.changeOwningCostContexts = changeOwningCostContexts;
        this.originalChangeOwningCostContexts = mode == Mode.UPDATE
                ? Objects.requireNonNull(originalChangeOwningCostContexts)
                : originalChangeOwningCostContexts;
        this.mode = mode;
    }

    public List<ChangeOwningCostContext> getChangeOwningCostContexts() {
        return changeOwningCostContexts;
    }

    public Optional<List<ChangeOwningCostContext>> getOriginalChangeOwningCostContexts() {
        return Optional.ofNullable(originalChangeOwningCostContexts);
    }

    public Mode getMode() {
        return mode;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        QuotaChangeRequestOwningCostContext that = (QuotaChangeRequestOwningCostContext) o;
        return Objects.equals(changeOwningCostContexts, that.changeOwningCostContexts) && Objects.equals(originalChangeOwningCostContexts, that.originalChangeOwningCostContexts) && mode == that.mode;
    }

    @Override
    public int hashCode() {
        return Objects.hash(changeOwningCostContexts, originalChangeOwningCostContexts, mode);
    }

    @Override
    public String toString() {
        return "QuotaChangeRequestOwningCostContext{" +
                "changeOwningCostContexts=" + changeOwningCostContexts +
                ", originalChangeOwningCostContexts=" + originalChangeOwningCostContexts +
                ", mode=" + mode +
                '}';
    }

    public Builder copyBuilder() {
        return new Builder()
                .changeOwningCostContexts(changeOwningCostContexts)
                .originalChangeOwningCostContexts(originalChangeOwningCostContexts)
                .mode(mode);
    }

    public static Builder builder() {
        return new Builder();
    }

    public static class Builder {
        private List<ChangeOwningCostContext> changeOwningCostContexts;
        private List<ChangeOwningCostContext> originalChangeOwningCostContexts;
        private Mode mode;

        public Builder changeOwningCostContexts(List<ChangeOwningCostContext> changeOwningCostContexts) {
            this.changeOwningCostContexts = changeOwningCostContexts;
            return this;
        }

        public Builder originalChangeOwningCostContexts(List<ChangeOwningCostContext> originalChangeOwningCostContexts) {
            this.originalChangeOwningCostContexts = originalChangeOwningCostContexts;
            return this;
        }

        public Builder mode(Mode mode) {
            this.mode = mode;
            return this;
        }

        public QuotaChangeRequestOwningCostContext build() {
            return new QuotaChangeRequestOwningCostContext(
                    Objects.requireNonNull(changeOwningCostContexts),
                    originalChangeOwningCostContexts,
                    Objects.requireNonNull(mode)
            );
        }
    }

    public enum Mode {
        REFRESH,
        UPDATE,
        CREATE,
    }
}
