package ru.kirillius.pf.sdn.flow;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import ru.kirillius.pf.sdn.api.Networking.IPv4Subnet;
import ru.kirillius.pf.sdn.api.Networking.NetworkScope;
import ru.kirillius.pf.sdn.api.flow.CallContext;
import ru.kirillius.pf.sdn.api.flow.FlowFunction;
import ru.kirillius.pf.sdn.api.properties.IntegerConstraint;
import ru.kirillius.pf.sdn.api.properties.PropertyDescriptor;
import ru.kirillius.pf.sdn.api.properties.PropertyType;

import java.util.*;
import java.util.regex.Pattern;

@Slf4j
@RequiredArgsConstructor
@Deprecated
public class ResourceFilterObsolete implements FlowFunction {

    private final static String SUBNETS = "subnets";
    private final static String DOMAINS = "domains";
    private final static String ASN = "asn";

    private final static Map<String, PropertyDescriptor> properties;

    static {
        properties = new HashMap<>();
        properties.put(SUBNETS, PropertyDescriptor.builder().type(PropertyType.SUBNET).array(true).required(false).defaultValue(null).build());
        properties.put(DOMAINS, PropertyDescriptor.builder().type(PropertyType.STRING).array(true).required(false).defaultValue(null).build());
        properties.put(ASN, PropertyDescriptor.builder().type(PropertyType.INTEGER).array(true).required(false).defaultValue(null).build().addConstraint(new IntegerConstraint(1, 99999))); //TODO какой max asn?);
    }

    @Override
    public int getInputCount() {
        return 1;
    }

    @Override
    public int getOutputCount() {
        return 1;
    }

    @Override
    public List<String> getInputNames() {
        return List.of("input");
    }

    @Override
    public List<String> getOutputNames() {
        return List.of("output");
    }

    @Override
    public void apply(CallContext context) {
        var output = new NetworkScope();
        var source = context.getSources().getFirst();
        var properties = context.getProperties();

        if (properties.containsKey(SUBNETS)) {
            var filtered = Arrays.stream(properties.get(SUBNETS).split(Pattern.quote(",")))
                    .filter(s -> !s.isBlank())
                    .map(IPv4Subnet::new)
                    .toList();
            output.setSubnets(source.getSubnets().stream().filter(subnet -> !filtered.contains(subnet)).toList());
        } else {
            output.setSubnets(source.getSubnets());
        }

        if (properties.containsKey(DOMAINS)) {
            var filtered = Arrays.stream(properties.get(DOMAINS).split(Pattern.quote(",")))
                    .filter(s -> !s.isBlank())
                    .toList();
            output.setDomains(source.getDomains().stream().filter(domain -> !filtered.contains(domain)).toList());
        } else {
            output.setDomains(source.getDomains());
        }

        if (properties.containsKey(ASN)) {
            var filtered = Arrays.stream(properties.get(ASN).split(Pattern.quote(",")))
                    .filter(s -> !s.isBlank())
                    .map(Integer::parseInt)
                    .toList();
            output.setASN(source.getASN().stream().filter(asn -> !filtered.contains(asn)).toList());
        } else {
            output.setASN(source.getASN());
        }

        context.setOutputs(List.of(output));
    }

    @Override
    public Map<String, PropertyDescriptor> getProperties() {
        return Collections.unmodifiableMap(properties);
    }

    @Override
    public boolean hasInputs() {
        return true;
    }

    @Override
    public boolean hasOutputs() {
        return true;
    }

}
