package ru.yandex.webmaster3.core.sitestructure;

import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Set;

import com.google.common.collect.Iterables;

/**
 * @author avhaliullin
 * TODO !!! ВНИМАНИЕ: При любых изменениях необходимо синхронизировать логику с /wmconsole/version3/library/jupiter/search_url_status
 */
public class SearchUrlStatusUtil {
    public static SearchUrlStatusEnum raw2View(RawSearchUrlStatusEnum statusEnum, boolean searchable) {
        if (searchable) {
            return SearchUrlStatusEnum.INDEXED_SEARCHABLE; // WMC-6146 - use same status for all searchable docs
        }
        if (statusEnum == null) {
            return null;
        }
        switch (statusEnum) {
            case NOTHING_FOUND:
                return SearchUrlStatusEnum.NOTHING_FOUND;
            case HOST_ERROR:
                return SearchUrlStatusEnum.HOST_ERROR;
            case REDIRECT:
                return SearchUrlStatusEnum.REDIRECT_NOTSEARCHABLE;
            case HTTP_ERROR:
                return SearchUrlStatusEnum.HTTP_ERROR;
            case NOT_CANONICAL:
                return SearchUrlStatusEnum.NOT_CANONICAL;
            case NOT_MAIN_MIRROR:
                return SearchUrlStatusEnum.NOT_MAIN_MIRROR;
            case PARSER_ERROR:
                return SearchUrlStatusEnum.PARSER_ERROR;
            case ROBOTS_HOST_ERROR:
                return SearchUrlStatusEnum.ROBOTS_HOST_ERROR;
            case ROBOTS_URL_ERROR:
                return SearchUrlStatusEnum.ROBOTS_URL_ERROR;
            //noinspection fallthrough
            case SEMIDUP:
                return SearchUrlStatusEnum.SEMIDUP;
            case INDEXED:
            case SPAM:
            case SR:
                return SearchUrlStatusEnum.SR;
            case CLEAN_PARAMS:
                return SearchUrlStatusEnum.CLEAN_PARAMS;
            case NO_INDEX:
                return SearchUrlStatusEnum.NO_INDEX;
            case BAD_MIME_TYPE:
                return SearchUrlStatusEnum.BAD_MIME_TYPE;
            case OTHER:
            case FRESH:
                return SearchUrlStatusEnum.OTHER;
            default:
                return SearchUrlStatusEnum.SR;
        }
    }

    private static final EnumMap<SearchUrlStatusEnum, EnumSet<RawSearchUrlStatusEnum>> REVERSE_MAPPING =
            new EnumMap<>(SearchUrlStatusEnum.class);

    static {
        for (SearchUrlStatusEnum status : SearchUrlStatusEnum.values()) {
            REVERSE_MAPPING.put(status, EnumSet.noneOf(RawSearchUrlStatusEnum.class));
        }
        for (RawSearchUrlStatusEnum rawStatus : RawSearchUrlStatusEnum.values()) {
            SearchUrlStatusEnum status = raw2View(rawStatus, false);
            REVERSE_MAPPING.get(status).add(rawStatus);
        }
        // костыли для поддержки статутов, которые по идее не должны попадать в view2AllRaw
        // но добавлены из соображений совместимости со старой функцией
        REVERSE_MAPPING.get(SearchUrlStatusEnum.INDEXED_SEARCHABLE).add(RawSearchUrlStatusEnum.INDEXED);
        REVERSE_MAPPING.get(SearchUrlStatusEnum.INDEXED_NOTSEARCHABLE).add(RawSearchUrlStatusEnum.INDEXED);
        REVERSE_MAPPING.get(SearchUrlStatusEnum.REDIRECT_SEARCHABLE).add(RawSearchUrlStatusEnum.REDIRECT);
    }

    public static Set<RawSearchUrlStatusEnum> view2AllRaw(SearchUrlStatusEnum status) {
        return REVERSE_MAPPING.get(status);
    }

    public static void main(String[] args) {
        System.out.println(view2AllRaw(SearchUrlStatusEnum.OTHER));
    }

    public static RawSearchUrlStatusEnum view2Raw(SearchUrlStatusEnum status) {
        Set<RawSearchUrlStatusEnum> rawStatuses = REVERSE_MAPPING.get(status);
        return Iterables.getFirst(rawStatuses, null);
    }

    public static boolean isSearchable(SearchUrlStatusEnum status) {
        return status == SearchUrlStatusEnum.INDEXED_SEARCHABLE || status == SearchUrlStatusEnum.REDIRECT_SEARCHABLE;
    }

    //status + is_added = причина
    public static SearchUrlStatusEnum viewFromJupiterStatusId(int id, boolean searchable) {
        SearchUrlStatusEnum result = viewFromJupiterStatusId(id, null, searchable);
        if (result == null) {
            throw new IllegalArgumentException("Unknown url status with id " + id);
        }
        return result;
    }

    public static SearchUrlStatusEnum viewFromJupiterStatusId(int id, SearchUrlStatusEnum defaultValue, boolean searchable) {
        RawSearchUrlStatusEnum raw = RawSearchUrlStatusEnum.R.fromValueOrNull(id);
        return raw == null ? defaultValue : raw2View(raw, searchable);
    }
}
