package ru.yandex.autodoc.common.doc.view.handlers;

import org.apache.commons.lang3.tuple.Pair;
import ru.yandex.autodoc.common.doc.params.ParamType;
import ru.yandex.autodoc.common.doc.types.AnyObjectModel;
import ru.yandex.autodoc.common.doc.types.CollectionType;
import ru.yandex.autodoc.common.doc.types.EnumType;
import ru.yandex.autodoc.common.doc.view.Markup;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author avhaliullin
 */
public final class TypeMarkupUtil {
    public static Markup typeToMarkup(ObjectFormatResolver objectFormatResolver, ParamType tpe, String id) {
        if (tpe instanceof ParamType.JsonParam) {
            ParamType.JsonParam jsonType = (ParamType.JsonParam) tpe;
            return new Markup.Popup(id, tpe.getName(), tpe.getName(), new Markup.DocumentedJson(jsonType.format));
        } else if (tpe instanceof ParamType.DocumentedEnum) {
            return enumMarkup((ParamType.DocumentedEnum) tpe, id, tpe.getName());
        } else if (tpe instanceof EnumType) {
            return enumMarkup((EnumType) tpe, false);
        } else if (tpe instanceof CollectionType) {
            CollectionType ct = (CollectionType) tpe;
            return Markup.group(
                    Markup.textOrEmpty("collection of "),
                    typeToMarkup(objectFormatResolver, ct.getElementType(), id)
            );
        } else if (tpe instanceof AnyObjectModel) {
            AnyObjectModel obj = (AnyObjectModel) tpe;
            return new Markup.Popup(id, tpe.getName(), tpe.getName(), objectFormatResolver.resolve(obj));
        } else {
            return Markup.textOrEmpty(tpe.getName());
        }
    }

    public static Markup enumMarkup(EnumType tpe, boolean valueAsAnchor) {
        if (!tpe.getEntries().isEmpty()) {
            return new Markup.Popup(
                    tpe.getName(),
                    valueAsAnchor ? tpe.getEntries().get(0).getValue() : tpe.getName(),
                    tpe.getName(),
                    Markup.table(
                            tpe.getEntries(),
                            "Значение", "Описание",
                            e -> Markup.textOrEmpty(e.getValue()), e -> Markup.textOrEmpty(e.getDescription())
                    )
            );
        } else {
            return new Markup.Text("");
        }
    }

    public static Markup enumMarkup(String id, String anchor, String title, List<Pair<Markup, Markup>> entries) {
        return new Markup.Popup(
                id,
                anchor,
                title,
                Markup.table(
                        entries,
                        "Значение", "Описание",
                        Pair::getLeft, Pair::getRight
                )
        );
    }

    public static Markup enumMarkup(ParamType.DocumentedEnum documentedEnum, String id, String anchor) {
        return enumMarkup(
                id,
                anchor == null ? documentedEnum.getName() : anchor,
                documentedEnum.getName(),
                documentedEnum.universe.stream()
                        .map(e -> Pair.of(
                                (Markup) new Markup.B(Markup.textOrEmpty(e.value)),
                                Markup.textOrEmpty(e.description)
                        ))
                        .collect(Collectors.toList())
        );
    }
}
