package ru.yandex.direct.web.entity.banner.converter;

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

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

import ru.yandex.direct.core.entity.adgroup.model.AdGroupType;
import ru.yandex.direct.core.entity.banner.model.BannerMeasurer;
import ru.yandex.direct.core.entity.banner.model.BannerMeasurerSystem;
import ru.yandex.direct.core.entity.banner.model.BannerWithCreative;
import ru.yandex.direct.core.entity.banner.model.BannerWithHref;
import ru.yandex.direct.core.entity.banner.model.BannerWithSystemFields;
import ru.yandex.direct.core.entity.banner.model.CpmAudioBanner;
import ru.yandex.direct.core.entity.banner.model.CpmBanner;
import ru.yandex.direct.core.entity.banner.model.CpmIndoorBanner;
import ru.yandex.direct.core.entity.banner.model.CpmOutdoorBanner;
import ru.yandex.direct.web.entity.banner.model.WebBannerCreative;
import ru.yandex.direct.web.entity.banner.model.WebBannerMeasurerSystem;
import ru.yandex.direct.web.entity.banner.model.WebCpmBanner;
import ru.yandex.direct.web.entity.banner.model.WebPixel;

import static java.util.Collections.emptyList;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static ru.yandex.direct.utils.CommonUtils.ifNotNull;
import static ru.yandex.direct.utils.FunctionalUtils.mapList;
import static ru.yandex.direct.utils.NumberUtils.nullIfZero;
import static ru.yandex.direct.utils.StringUtils.ifNotBlank;
import static ru.yandex.direct.web.entity.banner.converter.BannerConverter.toCoreTurbolandingId;

@ParametersAreNonnullByDefault
public class CpmBannerConverter {

    private CpmBannerConverter() {
    }

    public static List<BannerWithSystemFields> webBannersToCoreCpmBanners(AdGroupType adGroupType,
                                                                          @Nullable List<WebCpmBanner> webBanners) {
        return mapList(webBanners, webBanner -> webBannerToCoreCpmBanner(adGroupType, webBanner));
    }

    @Nullable
    public static BannerWithSystemFields webBannerToCoreCpmBanner(AdGroupType adGroupType,
                                                                  @Nullable WebCpmBanner webBanner) {
        if (webBanner == null) {
            return null;
        }

        final BannerWithSystemFields banner;
        switch (adGroupType) {
            case CPM_OUTDOOR: {
                banner = createCpmOutdoorBanner();
                break;
            }
            case CPM_INDOOR: {
                banner = createCpmIndoorBanner();
                break;
            }
            case CPM_AUDIO: {
                banner = createCpmAudioBanner(webBanner);
                break;
            }
            default:
                banner = createCpmBanner(webBanner);
        }

        String href = !isBlank(webBanner.getUrlProtocol()) && !isBlank(webBanner.getHref()) ?
                webBanner.getUrlProtocol() + webBanner.getHref() :
                null;
        String creativeId = ifNotNull(webBanner.getCreative(), WebBannerCreative::getCreativeId);
        //noinspection ConstantConditions
        if (banner instanceof BannerWithHref) {
            ((BannerWithHref) banner).withHref(href);
        }

        if (banner instanceof BannerWithCreative) {
            ((BannerWithCreative) banner).withCreativeId(ifNotBlank(creativeId, Long::parseLong));
        }

        return banner
                .withId(nullIfZero(webBanner.getId()));
    }

    private static CpmBanner createCpmBanner(WebCpmBanner webBanner) {
        var pixelUrls = mapList(webBanner.getPixels(), WebPixel::getUrl);
        var measurers = mapList(webBanner.getMeasurers(),
                m -> new BannerMeasurer()
                        .withBannerMeasurerSystem(toBannerMeasurerSystem(m.getMeasurerSystem()))
                        .withParams(m.getParams())
                        .withHasIntegration(m.getHasIntegration()));
        return new CpmBanner()
                // Модель WebBannerTurbolanding используется только в старом интерфейсе,
                // в новом следует использовать turbolandingId
                .withTurboLandingId(toCoreTurbolandingId(webBanner.getTurbolanding()))
                .withTurboLandingHrefParams(webBanner.getTurbolandingHrefParams())
                .withPixels(Optional.ofNullable(pixelUrls).orElse(emptyList()))
                .withTnsId(webBanner.getTnsId())
                .withMeasurers(Optional.ofNullable(measurers).orElse(emptyList()));
    }

    private static CpmOutdoorBanner createCpmOutdoorBanner() {
        return new CpmOutdoorBanner();
    }

    private static CpmIndoorBanner createCpmIndoorBanner() {
        return new CpmIndoorBanner();
    }

    private static CpmAudioBanner createCpmAudioBanner(WebCpmBanner webBanner) {
        List<String> pixelUrls = mapList(webBanner.getPixels(), WebPixel::getUrl);
        return new CpmAudioBanner()
                .withPixels(pixelUrls == null ? emptyList() : pixelUrls);
    }

    @Nullable
    private static BannerMeasurerSystem toBannerMeasurerSystem(@Nullable WebBannerMeasurerSystem measurerSystem) {
        if (measurerSystem == null) {
            return null;
        }

        switch (measurerSystem) {
            case ADMETRICA:
                return BannerMeasurerSystem.ADMETRICA;
            case MEDIASCOPE:
                return BannerMeasurerSystem.MEDIASCOPE;
            case ADLOOX:
                return BannerMeasurerSystem.ADLOOX;
            case MOAT:
                return BannerMeasurerSystem.MOAT;
            case DV:
                return BannerMeasurerSystem.DV;
            case ADRIVER:
                return BannerMeasurerSystem.ADRIVER;
            case SIZMEK:
                return BannerMeasurerSystem.SIZMEK;
            case INTEGRAL_AD_SCIENCE:
                return BannerMeasurerSystem.INTEGRAL_AD_SCIENCE;
            case WEBORAMA:
                return BannerMeasurerSystem.WEBORAMA;
            case OMI:
                return BannerMeasurerSystem.OMI;
            default:
                throw new IllegalStateException("No such value: " + measurerSystem);
        }
    }
}
