package ru.yandex.canvas.service.rtbhost;

import java.util.Collections;
import java.util.List;
import java.util.Map;

import ru.yandex.adv.direct.media.Dimension;
import ru.yandex.adv.direct.media.HtmlParameters;
import ru.yandex.adv.direct.media.Options;
import ru.yandex.adv.direct.media.PresetParameters;
import ru.yandex.canvas.model.Bundle;
import ru.yandex.canvas.model.CreativeData;
import ru.yandex.canvas.model.MediaSet;
import ru.yandex.canvas.model.MediaSetItem;
import ru.yandex.canvas.model.MediaSetSubItem;
import ru.yandex.canvas.model.SmartCenter;
import ru.yandex.canvas.model.elements.Element;
import ru.yandex.canvas.model.elements.ElementWithMaxLength;
import ru.yandex.canvas.model.presets.PresetItem;
import ru.yandex.canvas.model.rtbhost.DimensionBuilder;

import static java.util.stream.Collectors.toList;

public class HtmlParametersBuilder {
    private HtmlParameters.Builder builder;

    public HtmlParametersBuilder() {
        builder = HtmlParameters.newBuilder();
    }

    public void setCreativeData(CreativeData data) {
        builder.setData(buildCreativeData(data));
    }

    public HtmlParameters build() {
        return builder.build();
    }

    private static ru.yandex.adv.direct.media.CreativeData buildCreativeData(CreativeData data) {
        var builder = ru.yandex.adv.direct.media.CreativeData.newBuilder();

        var size = DimensionBuilder.build(data.getWidth(), data.getHeight());
        if (size != null) {
            builder.setSize(size);
        }

        var logoSize = DimensionBuilder.build(data.getLogoWidth(), data.getLogoHeight());
        if (logoSize != null) {
            builder.setLogoSize(logoSize);
        }

        var options = buildOptions(data.getOptions());
        if (options != null) {
            builder.setOptions(options);
        }

        builder.addAllElements(buildElements(data.getElements()));
        builder.addAllMediaSets(buildMediaSets(data.getMediaSets()));

        var bundle = buildBundle(data.getBundle());
        if (bundle != null) {
            builder.setBundle(bundle);
        }

        if (data.getClickUrl() != null) {
            builder.setClickUrl(data.getClickUrl());
        }

        return builder.build();
    }

    private static Options buildOptions(CreativeData.Options options) {
        if (options == null) {
            return null;
        }

        var builder = Options.newBuilder();

        if (options.getBackgroundColor() != null) {
            builder.setBackgroundColor(options.getBackgroundColor());
        }
        if (options.getBorderColor() != null) {
            builder.setBorderColor(options.getBorderColor());
        }
        if (options.getHasAnimation() != null) {
            builder.setHasAnimation(options.getHasAnimation());
        }
        if (options.getHasSocialLabel() != null) {
            builder.setHasSocialLabel(options.getHasSocialLabel());
        }
        if (options.getIsAdaptive() != null) {
            builder.setIsAdaptive(options.getIsAdaptive());
        }

        var minSize = DimensionBuilder.build(options.getMinWidth(), options.getMinHeight());
        if (minSize != null) {
            builder.setMinSize(minSize);
        }

        return builder.build();
    }

    private static ru.yandex.adv.direct.media.Bundle buildBundle(Bundle bundle) {
        if (bundle == null) {
            return null;
        }

        var builder = ru.yandex.adv.direct.media.Bundle.newBuilder();
        if (bundle.getName() != null) {
            builder.setName(bundle.getName());
        }
        builder.setVersion(bundle.getVersion());
        return builder.build();
    }

    private static List<ru.yandex.adv.direct.media.Element> buildElements(List<Element> elements) {
        if (elements == null) {
            return Collections.emptyList();
        }

        return elements.stream().map(e -> buildElement(e)).collect(toList());
    }

    private static ru.yandex.adv.direct.media.Element buildElement(Element e) {
        var builder = ru.yandex.adv.direct.media.Element.newBuilder();

        if (e.getType() != null) {
            builder.setType(e.getType());
        }
        if (e.getMediaSet() != null) {
            builder.setMediaSet(e.getMediaSet());
        }
        if (e instanceof ElementWithMaxLength) {
            var elementWithMaxLength = (ElementWithMaxLength) e;
            builder.setMaxLength(elementWithMaxLength.getMaxLength());
        }
        builder.setOptions(e.getOptions().toProto());
        builder.setIsAvailable(e.getAvailable());

        return builder.build();
    }

    private static List<ru.yandex.adv.direct.media.MediaSet> buildMediaSets(Map<String, MediaSet> mediaSets) {
        if (mediaSets == null) {
            return Collections.emptyList();
        }

        return mediaSets.entrySet().stream().map(entry -> buildMediaSet(entry.getKey(), entry.getValue())).collect(toList());
    }

    private static ru.yandex.adv.direct.media.MediaSet buildMediaSet(String name, MediaSet value) {
        var builder = ru.yandex.adv.direct.media.MediaSet.newBuilder();
        if (name != null) {
            builder.setName(name);
        }
        if (value != null) {
            builder.addAllItems(buildMediaSetItems(value.getItems()));
        }
        return builder.build();
    }

    private static List<ru.yandex.adv.direct.media.MediaSetItem> buildMediaSetItems(List<MediaSetItem> items) {
        if (items == null) {
            return Collections.emptyList();
        }
        return items.stream().map(item -> buildMediaSetItem(item)).collect(toList());
    }

    private static ru.yandex.adv.direct.media.MediaSetItem buildMediaSetItem(MediaSetItem item) {
        var builder = ru.yandex.adv.direct.media.MediaSetItem.newBuilder();
        if (item.getType() != null) {
            builder.setType(item.getType());
        }
        builder.addAllItems(buildMediaSetSubItems(item.getItems()));
        return builder.build();
    }

    private static List<ru.yandex.adv.direct.media.MediaSetSubItem> buildMediaSetSubItems(List<MediaSetSubItem> items) {
        if (items == null) {
            return Collections.emptyList();
        }
        return items.stream().map(item -> buildMediaSetSubItem(item)).collect(toList());
    }

    private static ru.yandex.adv.direct.media.MediaSetSubItem buildMediaSetSubItem(MediaSetSubItem item) {
        var builder = ru.yandex.adv.direct.media.MediaSetSubItem.newBuilder();

        if (item.getFileId() != null) {
            builder.setFileId(item.getFileId());
        }
        if (item.getCroppedFileId() != null) {
            builder.setCroppedFileId(item.getCroppedFileId());
        }
        if (item.getUrl() != null) {
            builder.setUrl(item.getUrl());
        }

        Dimension size = DimensionBuilder.build(item.getWidth(), item.getHeight());
        if (size != null) {
            builder.setSize(size);
        }

        if (item.getAlias() != null) {
            builder.setAlias(item.getAlias());
        }
        builder.setIsDefault(item.isDefaultValue());
        builder.addAllSmartCenters(buildSmartCenters(item.getSmartCenters()));

        return builder.build();
    }

    private static List<ru.yandex.adv.direct.media.SmartCenter> buildSmartCenters(List<SmartCenter> smartCenters) {
        if (smartCenters == null) {
            return Collections.emptyList();
        }
        return smartCenters.stream().map(item -> buildSmartCenter(item)).collect(toList());
    }

    private static ru.yandex.adv.direct.media.SmartCenter buildSmartCenter(SmartCenter smartCenter) {
        var builder = ru.yandex.adv.direct.media.SmartCenter.newBuilder();
        builder.setW(smartCenter.getW());
        builder.setH(smartCenter.getH());
        builder.setX(smartCenter.getX());
        builder.setY(smartCenter.getY());
        return builder.build();
    }

    public void setMinSize(Integer minWidth, Integer minHeight) {
        Dimension minSize = DimensionBuilder.build(minWidth, minHeight);
        if (minSize != null) {
            builder.setMinSize(minSize);
        }
    }

    public void setMaxSize(Integer maxWidth, Integer maxHeight) {
        Dimension maxSize = DimensionBuilder.build(maxWidth, maxHeight);
        if (maxSize != null) {
            builder.setMaxSize(maxSize);
        }
    }

    public void setPresetItem(PresetItem presetItem) {
        // Пока что из preset'а нам нужны только элементы, чтоб узнать исходные размеры изображений и видео.
        CreativeData presetData = new CreativeData();
        presetData.setElements(presetItem.getElements());

        var presetParametersBuilder = PresetParameters.newBuilder();
        presetParametersBuilder.setData(buildCreativeData(presetData));

        builder.setPreset(presetParametersBuilder.build());
    }
}
