package ru.yandex.webmaster3.core.turbo.model.menu;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.Getter;
import org.jetbrains.annotations.NotNull;

import ru.yandex.autodoc.common.doc.annotation.Description;

/**
 * Created by Oleg Bazdyrev on 16/03/2018.
 */
@Getter
@Description("Пункт меню для турбо-страницы")
public class TurboMenuItem {
    public static final TypeReference<List<TurboMenuItem>> LIST_REFERENCE = new TypeReference<>() {};

    @Description("Уникальный идентификатор пункта меню (для е-коммерс - id категории)")
    private final Long id;
    @Description("Подпись пункта меню")
    private final String label;
    @Description("Ссылка пункта меню")
    private final String url;
    @Description("Турбо-ссылка пункта меню")
    private final String turboUrl;
    @Description("Дочерние пункты меню")
    private final List<TurboMenuItem> submenu;

    public TurboMenuItem(@JsonProperty("id") Long id,
                         @JsonProperty("label") String label,
                         @JsonProperty("url") String url,
                         @JsonProperty("turboUrl") String turboUrl,
                         @JsonProperty("submenu") List<TurboMenuItem> submenu) {
        this.id = id;
        this.label = label;
        this.url = url;
        this.turboUrl = turboUrl;
        this.submenu = submenu;
    }


    public static List<TurboMenuItem> mergeUserAndAutoMenu(List<TurboMenuItem> userMenu, List<TurboMenuItem> autoMenu, boolean withUrl) {
        if (userMenu == null) {
            userMenu = Collections.emptyList();
        }
        if (autoMenu == null) {
            autoMenu = Collections.emptyList();
        }
        Map<Long, TurboMenuItem> autoMenuById = autoMenu.stream().collect(Collectors.toMap(TurboMenuItem::getId, Function.identity()));

        List<TurboMenuItem> result = new ArrayList<>();
        for (TurboMenuItem userItem : userMenu) {
            TurboMenuItem autoItem = autoMenuById.remove(userItem.getId());
            if (autoItem == null) {
                // такого пункта меню уже нет, выкидываем
                continue;
            }
            result.add(new TurboMenuItem(userItem.getId(),
                    autoItem.getLabel(),
                    withUrl ? autoItem.getUrl() : null,
                    withUrl ? autoItem.getTurboUrl() : null,
                    mergeUserAndAutoMenu(userItem.getSubmenu(), autoItem.getSubmenu(), withUrl))
            );
        }
        // добавим недостающие пункты из автоменю
        for (TurboMenuItem autoItem : autoMenu) {
            if (autoMenuById.containsKey(autoItem.getId())) {
                result.add(withUrl ? autoItem : copyWithoutUrl(autoItem));
            }
        }
        return result;
    }

    @NotNull
    private static TurboMenuItem copyWithoutUrl(@NotNull TurboMenuItem menuItem) {
        return new TurboMenuItem(menuItem.id, menuItem.label, null, null,
                menuItem.submenu.stream().map(TurboMenuItem::copyWithoutUrl).collect(Collectors.toList()));
    }

    public TurboMenuItem withUrl(String url) {
        return new TurboMenuItem(id, label, url, turboUrl, submenu);
    }

}
