package ru.yandex.direct.api.v5.entity.ads.container;

import java.util.EnumMap;
import java.util.List;
import java.util.Map;

import javax.annotation.ParametersAreNonnullByDefault;

import ru.yandex.direct.core.entity.adgroup.model.AdGroupType;
import ru.yandex.direct.core.entity.adgroup.model.ContentPromotionAdgroupType;
import ru.yandex.direct.core.entity.banner.model.BannerWithCreativeModeration;
import ru.yandex.direct.core.entity.banner.model.BannerWithSystemFields;
import ru.yandex.direct.core.entity.campaign.model.Campaign;
import ru.yandex.direct.core.entity.creative.model.Creative;
import ru.yandex.direct.core.entity.mobilecontent.model.MobileContent;
import ru.yandex.direct.core.entity.moderationdiag.model.ModerationDiag;
import ru.yandex.direct.core.entity.moderationreason.model.ModerationReasonObjectType;

import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.Collections.emptyList;

@ParametersAreNonnullByDefault
public class AdsGetContainer {

    private final BannerWithSystemFields ad;
    private final Boolean isStoppedByMonitoring;
    private final Campaign campaign;
    private final EnumMap<ModerationReasonObjectType, List<ModerationDiag>> reasonsByType;
    private final MobileContent mobileContent;
    private final BannerWithCreativeModeration bannerCreative;
    private final Creative creative;
    private AdGroupType adGroupType;
    private ContentPromotionAdgroupType contentPromotionAdgroupType;

    private AdsGetContainer(Builder builder) {
        BannerWithSystemFields ad = builder.getAd();
        checkNotNull(ad);
        this.ad = ad;

        Campaign campaign = builder.getCampaign();
        checkNotNull(campaign);
        this.campaign = campaign;

        this.isStoppedByMonitoring = builder.isStoppedByMonitoring();

        this.mobileContent = builder.getMobileContent();
        this.bannerCreative = builder.getBannerCreative();
        this.creative = builder.getCreative();
        this.adGroupType = builder.getAdGroupType();
        this.contentPromotionAdgroupType = builder.getContentPromotionAdgroupType();

        reasonsByType = new EnumMap<>(ModerationReasonObjectType.class);

        List<ModerationDiag> bannerModerationReasons = builder.getBannerModerationReasons();
        if (!bannerModerationReasons.isEmpty()) {
            setReasons(ModerationReasonObjectType.BANNER, bannerModerationReasons);
        }

        List<ModerationDiag> vcardModerationReasons = builder.getVCardModerationReasons();
        if (!vcardModerationReasons.isEmpty()) {
            setReasons(ModerationReasonObjectType.CONTACTINFO, vcardModerationReasons);
        }

        List<ModerationDiag> sitelinksModerationReasons = builder.getSitelinksModerationReasons();
        if (!sitelinksModerationReasons.isEmpty()) {
            setReasons(ModerationReasonObjectType.SITELINKS_SET, sitelinksModerationReasons);
        }

        List<ModerationDiag> displayHrefModerationReasons = builder.getDisplayHrefModerationReasons();
        if (!displayHrefModerationReasons.isEmpty()) {
            setReasons(ModerationReasonObjectType.DISPLAY_HREF, displayHrefModerationReasons);
        }

        List<ModerationDiag> imageModerationReasons = builder.getImageModerationReasons();
        if (!imageModerationReasons.isEmpty()) {
            setReasons(ModerationReasonObjectType.IMAGE, imageModerationReasons);
        }
    }

    public BannerWithSystemFields getAd() {
        return ad;
    }

    public Boolean isStoppedByMonitoring() {
        return isStoppedByMonitoring;
    }

    public Campaign getCampaign() {
        return campaign;
    }

    public MobileContent getMobileContent() {
        return mobileContent;
    }

    public BannerWithCreativeModeration getBannerCreative() {
        return bannerCreative;
    }

    public Creative getCreative() {
        return creative;
    }

    private void setReasons(ModerationReasonObjectType type, List<ModerationDiag> reasons) {
        reasonsByType.put(type, reasons);
    }

    private List<ModerationDiag> getReasons(ModerationReasonObjectType type) {
        List<ModerationDiag> reasons = reasonsByType.get(type);
        return reasons == null ? emptyList() : reasons;
    }

    public List<ModerationDiag> getBannerModerationReasons() {
        return getReasons(ModerationReasonObjectType.BANNER);
    }

    public List<ModerationDiag> getVCardModerationReasons() {
        return getReasons(ModerationReasonObjectType.CONTACTINFO);
    }

    public List<ModerationDiag> getSitelinksModerationReasons() {
        return getReasons(ModerationReasonObjectType.SITELINKS_SET);
    }

    public List<ModerationDiag> getDisplayHrefModerationReasons() {
        return getReasons(ModerationReasonObjectType.DISPLAY_HREF);
    }

    public List<ModerationDiag> getImageModerationReasons() {
        return getReasons(ModerationReasonObjectType.IMAGE);
    }

    public AdGroupType getAdGroupType() {
        return adGroupType;
    }

    public ContentPromotionAdgroupType getContentPromotionAdgroupType() {
        return contentPromotionAdgroupType;
    }

    public static class Builder {

        private BannerWithSystemFields ad;
        private Boolean isStoppedByMonitoring = false;
        private Campaign campaign;
        private MobileContent mobileContent;
        private BannerWithCreativeModeration bannerCreative;
        private Creative creative;
        private Map<ModerationReasonObjectType, List<ModerationDiag>> reasonsByType;
        private AdGroupType adGroupType;
        private ContentPromotionAdgroupType contentPromotionAdgroupType;

        public void setReasonsByType(
                Map<ModerationReasonObjectType, List<ModerationDiag>> reasonsByType) {
            this.reasonsByType = reasonsByType;
        }

        private void setReasons(ModerationReasonObjectType type, List<ModerationDiag> reasons) {
            if (reasonsByType == null) {
                reasonsByType = new EnumMap<>(ModerationReasonObjectType.class);
            }
            reasonsByType.put(type, reasons);
        }

        private List<ModerationDiag> getReasons(ModerationReasonObjectType type) {
            if (reasonsByType == null) {
                return emptyList();
            }
            List<ModerationDiag> reasons = reasonsByType.get(type);
            return reasons == null ? emptyList() : reasons;
        }

        public Builder isStoppedByMonitoring(Boolean isStoppedByMonitoring) {
            this.isStoppedByMonitoring = isStoppedByMonitoring;
            return this;
        }

        public Boolean isStoppedByMonitoring() {
            return isStoppedByMonitoring != null ? isStoppedByMonitoring : false;
        }

        public Builder withAd(BannerWithSystemFields ad) {
            this.ad = ad;
            return this;
        }

        public BannerWithSystemFields getAd() {
            return ad;
        }


        public Builder withCampaign(Campaign campaign) {
            this.campaign = campaign;
            return this;
        }

        public Campaign getCampaign() {
            return campaign;
        }

        public Builder withMobileContent(MobileContent mobileContent) {
            this.mobileContent = mobileContent;
            return this;
        }

        public MobileContent getMobileContent() {
            return mobileContent;
        }

        public Builder withBannerCreative(BannerWithCreativeModeration bannerCreative) {
            this.bannerCreative = bannerCreative;
            return this;
        }

        public BannerWithCreativeModeration getBannerCreative() {
            return bannerCreative;
        }

        public Builder withCreative(Creative creative) {
            this.creative = creative;
            return this;
        }

        public Creative getCreative() {
            return creative;
        }

        public Builder withBannerModerationReasons(List<ModerationDiag> reasons) {
            setReasons(ModerationReasonObjectType.BANNER, reasons);
            return this;
        }

        public List<ModerationDiag> getBannerModerationReasons() {
            return getReasons(ModerationReasonObjectType.BANNER);
        }

        public Builder withVCardModerationReasons(List<ModerationDiag> reasons) {
            setReasons(ModerationReasonObjectType.CONTACTINFO, reasons);
            return this;
        }

        public List<ModerationDiag> getVCardModerationReasons() {
            return getReasons(ModerationReasonObjectType.CONTACTINFO);
        }

        public Builder withSitelinksModerationReasons(List<ModerationDiag> reasons) {
            setReasons(ModerationReasonObjectType.SITELINKS_SET, reasons);
            return this;
        }

        public List<ModerationDiag> getSitelinksModerationReasons() {
            return getReasons(ModerationReasonObjectType.SITELINKS_SET);
        }

        public Builder withDisplayHrefModerationReasons(List<ModerationDiag> reasons) {
            setReasons(ModerationReasonObjectType.DISPLAY_HREF, reasons);
            return this;
        }

        public List<ModerationDiag> getDisplayHrefModerationReasons() {
            return getReasons(ModerationReasonObjectType.DISPLAY_HREF);
        }

        public Builder withImageModerationReasons(List<ModerationDiag> reasons) {
            setReasons(ModerationReasonObjectType.IMAGE, reasons);
            return this;
        }

        public List<ModerationDiag> getImageModerationReasons() {
            return getReasons(ModerationReasonObjectType.IMAGE);
        }

        public AdGroupType getAdGroupType() {
            return adGroupType;
        }

        public Builder withAdGroupType(AdGroupType adGroupType) {
            this.adGroupType = adGroupType;
            return this;
        }

        public ContentPromotionAdgroupType getContentPromotionAdgroupType() {
            return contentPromotionAdgroupType;
        }

        public Builder withContentPromotionAdgroupType(ContentPromotionAdgroupType contentPromotionAdgroupType) {
            this.contentPromotionAdgroupType = contentPromotionAdgroupType;
            return this;
        }

        public AdsGetContainer build() {
            return new AdsGetContainer(this);
        }
    }
}
