package ru.kirillius.pf.sdn.flow;

import lombok.RequiredArgsConstructor;
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.properties.PropertyDescriptor;
import ru.kirillius.pf.sdn.api.properties.PropertyType;
import ru.kirillius.pf.sdn.service.DomainResolverService;
import ru.kirillius.pf.sdn.service.DomainUpdaterService;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RequiredArgsConstructor
public class AutoResolveDomains extends CommonFunction {

    private final DomainUpdaterService domainCacheService;
    private final DomainResolverService domainResolverService;

    private final static String CLEAR = "clear";
    private final static Map<String, PropertyDescriptor> properties;

    static {
        properties = new HashMap<>();
        properties.put(CLEAR,
                PropertyDescriptor.builder()
                        .type(PropertyType.BOOLEAN)
                        .required(true)
                        .defaultValue(true)
                        .array(false)
                        .build()
        );
    }

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

        if (properties.containsKey(CLEAR) && properties.get(CLEAR).equals("true")) {
            output.getResolveDomains().clear();
        }

        source.getResolveDomains()
                .forEach(domain -> domainCacheService.getActualAddresses(domain)
                        .forEach(address -> output
                                .getSubnets()
                                .add(new IPv4Subnet(address, 32)
                                )
                        )
                );

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

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

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

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