package com.bonus.zlpt.common.swagger;

import com.bonus.zlpt.common.core.annotation.Excel;
import com.fasterxml.classmate.ResolvedType;
import com.fasterxml.classmate.TypeResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.StringUtils;
import springfox.documentation.service.AllowableListValues;
import springfox.documentation.service.AllowableRangeValues;
import springfox.documentation.service.AllowableValues;
import springfox.documentation.spring.web.DescriptionResolver;

import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class ApiModelPropertiesExtend  {

    private static final Logger LOGGER = LoggerFactory.getLogger(ApiModelPropertiesExtend.class);
    private static final Pattern RANGE_PATTERN = Pattern.compile("range([\\[(])(.*),(.*)([])])$");

    private ApiModelPropertiesExtend() {
        throw new UnsupportedOperationException();
    }

    static Function<Excel, AllowableValues> toAllowableValues() {
        return null;
    }

    public static AllowableValues allowableValueFromString(String allowableValueString) {
        AllowableValues allowableValues = new AllowableListValues(new ArrayList(), "LIST");
        String trimmed = allowableValueString.trim();
        Matcher matcher = RANGE_PATTERN.matcher(trimmed.replaceAll(" ", ""));
        if (matcher.matches()) {
            if (matcher.groupCount() != 4) {
                LOGGER.warn("Unable to parse range specified {} correctly", trimmed);
            } else {
                allowableValues = new AllowableRangeValues(matcher.group(2).contains("infinity") ? null : matcher.group(2), matcher.group(1).equals("("), matcher.group(3).contains("infinity") ? null : matcher.group(3), matcher.group(4).equals(")"));
            }
        } else {
            List singleVal;
            if (trimmed.contains(",")) {
                singleVal = (List) Stream.of(trimmed.split(",")).map(String::trim).filter((item) -> {
                    return !item.isEmpty();
                }).collect(Collectors.toList());
                allowableValues = new AllowableListValues(singleVal, "LIST");
            } else if (StringUtils.hasText(trimmed)) {
                singleVal = Collections.singletonList(trimmed);
                allowableValues = new AllowableListValues(singleVal, "LIST");
            }
        }

        return (AllowableValues)allowableValues;
    }

    static Function<Excel, String> toDescription(final DescriptionResolver descriptions) {
        return (annotation) -> {
            String description = "";
            if (!StringUtils.isEmpty(annotation.name())) {
                description = annotation.name();
            }

            return descriptions.resolve(description);
        };
    }

    static Function<Excel, ResolvedType> toType(final TypeResolver resolver) {
        return (annotation) -> {

                return resolver.resolve(Object.class, new Type[0]);

        };
    }

    public static Optional<Excel> findApiModePropertyAnnotation(AnnotatedElement annotated) {
        Optional<Excel> annotation = Optional.empty();
        if (annotated instanceof Method) {
            annotation = Optional.ofNullable((Excel) AnnotationUtils.findAnnotation((Method)annotated, Excel.class));
        }

        return (Optional)annotation.map(Optional::of).orElse(Optional.ofNullable((Excel) AnnotationUtils.getAnnotation(annotated, Excel.class)));
    }

    static Function<Excel, String> toExample() {
        return (annotation) -> {
            String example = "";
            return example;
        };
    }


}
