package ru.yandex.canvas.service.video;

import java.util.Arrays;
import java.util.Locale;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import javax.annotation.Nullable;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;

import ru.yandex.canvas.MongoLowerCaseEnum;
import ru.yandex.canvas.service.video.presets.PresetTag;

import static com.google.common.base.Preconditions.checkState;

public enum VideoCreativeType implements MongoLowerCaseEnum {
    TEXT(PresetTag.COMMON),
    CPC(PresetTag.CPC),
    CPM(PresetTag.CPM),
    NON_SKIPPABLE_CPM(PresetTag.NON_SKIPPABLE_CPM),
    PRICE_CAMPS_NON_SKIPPABLE_CPM(PresetTag.PRICE_CAMPS_NON_SKIPPABLE_CPM),
    PRICE_CAMPS_CPM(PresetTag.PRICE_CAMPS_CPM),
    CPM_YNDX_FRONTPAGE(PresetTag.PRICE_CAMPS_YNDX_FRONTPAGE_VIDEO),
    MOBILE_CONTENT(PresetTag.MOBILE_CONTENT),
    MOBILE_CONTENT_VIDEO(PresetTag.MOBILE_CONTENT_VIDEO),
    CPM_OUTDOOR(PresetTag.CPM_OUTDOOR),
    CPM_INDOOR(PresetTag.CPM_INDOOR),
    CPM_AUDIO(PresetTag.CPM_AUDIO),
    OVERLAY(PresetTag.OVERLAY),
    IN_BANNER(null),
    HTML5(null),
    VIDEO_CONSTRUCTOR(null),
    VIDEO_CONSTRUCTOR_FEED(null),
    UNKNOWN(null);

    private final PresetTag presetTag;

    private static Map<PresetTag, VideoCreativeType> byPresetTags = Arrays.stream(values())
            .filter(e -> e.presetTag != null)
            .collect(Collectors.toMap(e -> e.presetTag, Function.identity()));

    // "null" means conversion to preset tag is not available
    VideoCreativeType(@Nullable PresetTag presetTag) {
        this.presetTag = presetTag;
    }

    public PresetTag toPresetTag() {
        checkState(presetTag != null, "preset tag is not defined for {}", this.name());
        return presetTag;
    }

    @JsonValue
    public String getValue() {
        return toString().toLowerCase();
    }

    @JsonCreator
    public static VideoCreativeType fromString(String name) {
        return VideoCreativeType.valueOf(name.toUpperCase(Locale.ROOT));
    }

    public static VideoCreativeType fromPresetTag(PresetTag presetTag) {
        var value = byPresetTags.get(presetTag);
        if (value == null) {
            throw new IllegalArgumentException("Unknown preset tag: " + presetTag);
        }

        return value;
    }

    @Deprecated
    public static VideoCreativeType fromPresetId(Long presetId) {
        if (presetId >= 1 && presetId <= 5 || presetId >= 21 && presetId <= 28) {
            return VideoCreativeType.TEXT;
        } else if (presetId == 6 || presetId == 9 || presetId == 10) {
            return VideoCreativeType.CPM;
        } else if (presetId == 7) {
            return VideoCreativeType.NON_SKIPPABLE_CPM;
        } else if (presetId == 8) {
            return VideoCreativeType.PRICE_CAMPS_NON_SKIPPABLE_CPM;
        } else if (presetId >= 11 && presetId <= 17) {
            return VideoCreativeType.MOBILE_CONTENT;
        } else if (presetId >= 41 && presetId <= 55) {
            return VideoCreativeType.CPC;
        } else if (presetId >= 61 && presetId <= 67) {
            return VideoCreativeType.MOBILE_CONTENT_VIDEO;
        } else if (presetId == 101) {
            return VideoCreativeType.CPM_OUTDOOR;
        } else if (presetId == 201) {
            return VideoCreativeType.CPM_INDOOR;
        } else if (presetId >= 301 && presetId <= 304) {
            return VideoCreativeType.CPM_AUDIO;
        } else if (presetId == 351) {
            return VideoCreativeType.OVERLAY;
        } else {
            throw new IllegalArgumentException("Unknown preset id: " + presetId);
        }
    }

    // true - если тип креатива является одним из видеоконструкторных
    public static boolean isVideoConstructor(VideoCreativeType videoCreativeType) {
        return videoCreativeType == VideoCreativeType.VIDEO_CONSTRUCTOR ||
                videoCreativeType == VideoCreativeType.VIDEO_CONSTRUCTOR_FEED;
    }
}
