package ru.yandex.webmaster3.core.codes;

import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.jetbrains.annotations.NotNull;

import ru.yandex.webmaster3.core.data.HttpCodeInfo;

/**
 * @author aherman
 */
public enum LinkType {
    NORMAL(Arrays.asList(HttpCodeGroup.HTTP_GROUP_2XX), Arrays.asList(HttpCodeGroup.HTTP_GROUP_2XXX_SPECIAL)),
    REDIRECT(HttpCodeGroup.HTTP_301_MOVED_PERMANENTLY,
            HttpCodeGroup.HTTP_302_FOUND,
            HttpCodeGroup.HTTP_303_SEE_OTHER,
            HttpCodeGroup.HTTP_305_USE_PROXY,
            HttpCodeGroup.HTTP_307_TEMPORARY_REDIRECT,
            HttpCodeGroup.HTTP_308_PERMANENT_REDIRECT),
    BROKEN(),
    NOT_DOWNLOADED(HttpCodeGroup.HTTP_0_NOT_DOWNLOADED);

    private final Set<Integer> codes = new HashSet<>();

    LinkType(HttpCodeGroup... include) {
        for (HttpCodeGroup httpCodeGroup : include) {
            codes.addAll(httpCodeGroup.getCodesInternal());
        }
    }

    LinkType(List<HttpCodeGroup> include, List<HttpCodeGroup> exclude) {
        for (HttpCodeGroup httpCodeGroup : include) {
            codes.addAll(httpCodeGroup.getCodesInternal());
        }

        for (HttpCodeGroup httpCodeGroup : exclude) {
            codes.removeAll(httpCodeGroup.getCodesInternal());
        }
    }

    public static LinkType get(HttpCodeInfo linkHttpCode) {
        //downloaded
        if (linkHttpCode.getHttpCodeGroup() == HttpCodeGroup.HTTP_200_OK) {
            return NORMAL;
        }
        return get(linkHttpCode.getCode());
    }

    @NotNull
    public static LinkType get(int code) {
        if (HttpCodeGroup.HTTP_0_NOT_DOWNLOADED.contains(code)) {
            return NOT_DOWNLOADED;
        }

        if (HttpCodeGroup.HTTP_301_MOVED_PERMANENTLY.contains(code) ||
                HttpCodeGroup.HTTP_302_FOUND.contains(code) ||
                HttpCodeGroup.HTTP_303_SEE_OTHER.contains(code) ||
                HttpCodeGroup.HTTP_305_USE_PROXY.contains(code) ||
                HttpCodeGroup.HTTP_307_TEMPORARY_REDIRECT.contains(code) ||
                HttpCodeGroup.HTTP_308_PERMANENT_REDIRECT.contains(code)) {
            return REDIRECT;
        }

        if(HttpCodeGroup.HTTP_GROUP_2XX.contains(code)) {
            return NORMAL;
        } else if (HttpCodeGroup.HTTP_GROUP_2XXX.contains(code) && !HttpCodeGroup.HTTP_GROUP_2XXX_SPECIAL.contains(code)) {
            return NORMAL;
        }

        return BROKEN;
    }

    public boolean contains(int code) {
        return this == get(code);
    }

    public Set<Integer> getCodes() {
        return codes;
    }

    public static boolean isBroken(HttpCodeInfo code) {
        return get(code) == BROKEN;
    }

    public static boolean isBroken(int code) {
        return get(code) == BROKEN;
    }

    public static Set<Integer> getNotBrokenCodes() {
        Set<Integer> codes = new HashSet<>();
        codes.addAll(NORMAL.codes);
        codes.addAll(REDIRECT.codes);
        codes.addAll(NOT_DOWNLOADED.codes);
        return codes;
    }
}
