package ru.kirillius.pf.sdn.service;

import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import ru.kirillius.pf.sdn.Util.WorkerUtils;
import ru.kirillius.pf.sdn.api.Networking.IPv4Subnet;
import ru.kirillius.pf.sdn.entity.AutonomousSystemCacheEntry;
import ru.kirillius.pf.sdn.repository.AutonomousSystemCacheRepository;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutionException;

@Slf4j
@Setter
@RequiredArgsConstructor
@Service
public class AutonomousSystemCacheService {
    private final AutonomousSystemCacheRepository repository;
    private final AutonomousSystemResolverService resolverService;

    public void store(int number, List<IPv4Subnet> subnets) {
        if (repository.existsByNumber(number)) {
            repository.findByNumber(number).ifPresent(entry -> {
                entry.setPrefixes(subnets);
                repository.save(entry);
            });
        } else {
            repository.save(AutonomousSystemCacheEntry.builder().number(number).prefixes(subnets).build());
        }
    }

    public List<IPv4Subnet> load(int number) {

        var found = repository.findByNumber(number);

        if (found.isPresent()) {
            return found.get().getPrefixes();
        }

        var future = resolverService.getPrefixes(number);
        WorkerUtils.waitForCondition(() -> future.isCancelled() || future.isDone());

        if (future.isCancelled()) {
            return Collections.emptyList();
        }

        try {
            var entry = new AutonomousSystemCacheEntry();
            entry.setNumber(number);
            entry.setPrefixes(future.get());
            try {
                repository.save(entry);
            } catch (Exception e) {
                log.warn("Could not save CacheEntry for ASN " + number, e);
            }

            return entry.getPrefixes();
        } catch (InterruptedException | ExecutionException e) {
            log.error("Error while resolving ASN " + number, e);
        }
        return Collections.emptyList();

    }
}
