package ru.yandex.webmaster3.viewer.http.links2;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.common.collect.BoundType;
import com.google.common.collect.Range;
import ru.yandex.webmaster3.core.http.ActionResponse;

import java.util.Comparator;
import java.util.List;

/**
 * Created by ifilippov5 on 10.08.18.
 */
public abstract class GetExternalLinkSqiAndTldResponse implements ActionResponse {
    public static class OrdinaryResponse extends GetExternalLinkSqiAndTldResponse implements ActionResponse.NormalResponse {
        private List<SqiData> sqiData;
        private List<TldData> tldData;

        public OrdinaryResponse(List<SqiData> sqiData, List<TldData> tldData) {
            this.sqiData = sqiData;
            this.sqiData.sort(Comparator.comparing(a -> a.getName().getFrom(), Comparator.nullsLast(Comparator.naturalOrder())));
            this.tldData = tldData;
        }

        public List<SqiData> getSqi() {
            return sqiData;
        }

        public List<TldData> getTld() {
            return tldData;
        }
    }

    public static enum SqiRange {
        UNKNOWN(Range.upTo(0, BoundType.OPEN)),

        NO_SQI(Range.closedOpen(0, 1)),
        SQI_10(Range.closedOpen(10, 11)),
        SQI_20_50(Range.closed(20, 50)),
        SQI_60_100(Range.closed(60, 100)),
        SQI_110_1000(Range.closed(110, 1000)),
        SQI_1100_AND_MORE(Range.downTo(1010, BoundType.CLOSED))
        ;

        private final Range<Integer> range;

        SqiRange(Range<Integer> range) {
            this.range = range;
        }

        @JsonIgnore
        public Range<Integer> getRange() {
            return range;
        }

        public static GetExternalLinkSqiAndTldResponse.SqiRange findBy(int sqi) {
            for (GetExternalLinkSqiAndTldResponse.SqiRange sqiRange : values()) {
                if (sqiRange.range.contains(sqi)) {
                    return sqiRange;
                }
            }
            return UNKNOWN;
        }
    }

    public static class SqiData {
        public static class Indicator {
            private final GetExternalLinkSqiAndTldResponse.SqiRange name;

            public Indicator(GetExternalLinkSqiAndTldResponse.SqiRange name) {
                this.name = name;
            }

            public GetExternalLinkSqiAndTldResponse.SqiRange getName() {
                return name;
            }

            public Integer getFrom() {
                Range<Integer> range = name.range;
                return range.hasLowerBound() ? range.lowerEndpoint() : null;
            }

            public Integer getTo() {
                Range<Integer> range = name.range;
                return range.hasUpperBound() && range.upperBoundType() == BoundType.CLOSED
                        ? range.upperEndpoint() : null;
            }
        }

        private final GetExternalLinkSqiAndTldResponse.SqiData.Indicator name;
        private final long current;

        public SqiData(GetExternalLinkSqiAndTldResponse.SqiRange rangeName, long current) {
            this.name = new GetExternalLinkSqiAndTldResponse.SqiData.Indicator(rangeName);
            this.current = current;
        }

        public GetExternalLinkSqiAndTldResponse.SqiData.Indicator getName() {
            return name;
        }

        public long getCurrent() {
            return current;
        }
    }

    public static class TldData implements Comparable<GetExternalLinkSqiAndTldResponse.TldData> {
        private final String name;
        private final long current;

        public TldData(String name, long current) {
            this.name = name;
            this.current = current;
        }

        public String getName() {
            return name;
        }

        public long getCurrent() {
            return current;
        }

        @Override
        public int compareTo(GetExternalLinkSqiAndTldResponse.TldData o) {
            if (o != null) {
                return Long.compare(this.current, o.current);
            } else {
                return -1;
            }
        }
    }
}
