package ru.yandex.qe.dispenser.domain;

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

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import ru.yandex.qe.dispenser.domain.index.LongIndexBase;

public class CampaignResource extends LongIndexBase {

    private final long campaignId;
    private final long resourceId;
    private final boolean required;
    private final boolean defaultResource;
    @Nullable
    private final Long defaultAmount;
    @NotNull
    private final Settings settings;

    public CampaignResource(final long campaignId,
                            final long resourceId,
                            final boolean required,
                            final boolean defaultResource,
                            @Nullable final Long defaultAmount,
                            @NotNull final Settings settings) {
        this.campaignId = campaignId;
        this.resourceId = resourceId;
        this.required = required;
        this.defaultResource = defaultResource;
        this.defaultAmount = defaultAmount;
        this.settings = settings;
    }

    public long getCampaignId() {
        return campaignId;
    }

    public long getResourceId() {
        return resourceId;
    }

    public boolean isRequired() {
        return required;
    }

    public boolean isDefaultResource() {
        return defaultResource;
    }

    public Optional<Long> getDefaultAmount() {
        return Optional.ofNullable(defaultAmount);
    }

    @NotNull
    public Settings getSettings() {
        return settings;
    }

    @Override
    public boolean equals(final Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        final CampaignResource that = (CampaignResource) o;
        return campaignId == that.campaignId &&
                resourceId == that.resourceId &&
                required == that.required &&
                defaultResource == that.defaultResource &&
                Objects.equals(defaultAmount, that.defaultAmount) &&
                settings.equals(that.settings);
    }

    @Override
    public int hashCode() {
        return Objects.hash(campaignId, resourceId, required, defaultResource, defaultAmount, settings);
    }

    @Override
    public String toString() {
        return "CampaignResource{" +
                "campaignId=" + campaignId +
                ", resourceId=" + resourceId +
                ", required=" + required +
                ", defaultResource=" + defaultResource +
                ", defaultAmount=" + defaultAmount +
                ", settings=" + settings +
                "} " + super.toString();
    }

    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    public static final class Settings {

        private final List<Segmentation> segmentations;
        private final List<Long> bigOrders;
        private final List<SegmentsBigOrders> segmentsBigOrders;

        @JsonCreator
        public Settings(@JsonProperty("segmentations") final List<Segmentation> segmentations,
                        @JsonProperty("bigOrders") final List<Long> bigOrders,
                        @JsonProperty("segmentsBigOrders") final List<SegmentsBigOrders> segmentsBigOrders) {
            this.segmentations = segmentations != null ? segmentations : Collections.emptyList();
            this.bigOrders = bigOrders != null ? bigOrders : Collections.emptyList();
            this.segmentsBigOrders = segmentsBigOrders != null ? segmentsBigOrders : Collections.emptyList();
        }

        public List<Segmentation> getSegmentations() {
            return segmentations;
        }

        public List<Long> getBigOrders() {
            return bigOrders;
        }

        public List<SegmentsBigOrders> getSegmentsBigOrders() {
            return segmentsBigOrders;
        }

        @Override
        public boolean equals(final Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }
            final Settings settings = (Settings) o;
            return Objects.equals(segmentations, settings.segmentations) &&
                    Objects.equals(bigOrders, settings.bigOrders) &&
                    Objects.equals(segmentsBigOrders, settings.segmentsBigOrders);
        }

        @Override
        public int hashCode() {
            return Objects.hash(segmentations, bigOrders, segmentsBigOrders);
        }

        @Override
        public String toString() {
            return "Settings{" +
                    "segmentations=" + segmentations +
                    ", bigOrders=" + bigOrders +
                    ", segmentsBigOrders=" + segmentsBigOrders +
                    '}';
        }

    }

    public static final class Segmentation {

        private final long id;
        @NotNull
        private final List<Long> segments;

        @JsonCreator
        public Segmentation(@JsonProperty("id") final long id,
                            @JsonProperty("segments") final List<Long> segments) {
            this.id = id;
            this.segments = segments != null ? segments : Collections.emptyList();
        }

        public long getId() {
            return id;
        }

        @NotNull
        public List<Long> getSegments() {
            return segments;
        }

        @Override
        public boolean equals(final Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }
            final Segmentation that = (Segmentation) o;
            return id == that.id &&
                    segments.equals(that.segments);
        }

        @Override
        public int hashCode() {
            return Objects.hash(id, segments);
        }

        @Override
        public String toString() {
            return "Segmentation{" +
                    "id=" + id +
                    ", segments=" + segments +
                    '}';
        }

    }

    public static final class SegmentsBigOrders {

        @NotNull
        private final List<Long> segments;
        @NotNull
        private final List<Long> bigOrders;

        @JsonCreator
        public SegmentsBigOrders(@JsonProperty("segments") final List<Long> segments,
                                 @JsonProperty("bigOrders") final List<Long> bigOrders) {
            this.segments = segments != null ? segments : Collections.emptyList();
            this.bigOrders = bigOrders != null ? bigOrders : Collections.emptyList();
        }

        @NotNull
        public List<Long> getSegments() {
            return segments;
        }

        @NotNull
        public List<Long> getBigOrders() {
            return bigOrders;
        }

        @Override
        public boolean equals(final Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }
            final SegmentsBigOrders that = (SegmentsBigOrders) o;
            return segments.equals(that.segments) &&
                    bigOrders.equals(that.bigOrders);
        }

        @Override
        public int hashCode() {
            return Objects.hash(segments, bigOrders);
        }

        @Override
        public String toString() {
            return "SegmentsBigOrders{" +
                    "segments=" + segments +
                    ", bigOrders=" + bigOrders +
                    '}';
        }

    }

}
