package edu.prlab.tyler.iotgateway.gateway.services;

import edu.prlab.tyler.iotgateway.cloud.pojo.privacy.PrivacyChoice;
import edu.prlab.tyler.iotgateway.cloud.pojo.privacy.PrivacyPolicyReport;
import edu.prlab.tyler.iotgateway.gateway.model.PrivacyChoiceResponse;
import edu.prlab.tyler.iotgateway.gateway.pojo.PrivacyChoiceIndex;
import edu.prlab.tyler.iotgateway.gateway.repositories.PrivacyChoiceIndexRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.util.Optional;
import java.util.stream.StreamSupport;

@Service
public class PrivacyService {
    private RestTemplate template;
    private PrivacyChoiceIndexRepository privacyChoiceIndexRepository;

    private String cloudAddress;

    @Autowired
    public PrivacyService(PrivacyChoiceIndexRepository privacyChoiceIndexRepository,
                          RestTemplate template) {
        this.template = template;
        this.privacyChoiceIndexRepository = privacyChoiceIndexRepository;
    }

    @Value("${iotgateway.cloud.address}")
    private void setCloudAddress(String cloudAddress) {
        this.cloudAddress = cloudAddress;
    }

    public Optional<PrivacyPolicyReport> getRelatedPrivacyPolicies(String udn) {
        return Optional.ofNullable(template.getForObject(cloudAddress + "/privacy/" + udn, PrivacyPolicyReport.class));
    }

    public Optional<PrivacyChoiceResponse> setPrivacyPolicyChoice(PrivacyChoice privacyChoice) {
        return Optional.of(privacyChoice)
                .map(choice -> template.postForObject(cloudAddress + "/choice", choice, PrivacyChoice.class))
                .flatMap(choice -> Optional.ofNullable(privacyChoiceIndexRepository.save(PrivacyChoiceIndex.builder()
                        .id(choice.getId())
                        .localDateTime(LocalDateTime.now())
                        .build()))
                        .map(choiceIndex -> PrivacyChoiceResponse.builder()
                                .id(choice.getId())
                                .localDateTime(LocalDateTime.now())
                                .privacyContent(choice.getPrivacyContent())
                                .build()));
    }

//    public Optional<Iterable<PrivacyChoice>> getPrivacyPolicyChoices() {
//        return Optional.ofNullable(template.exchange(cloudAddress + "/choice", HttpMethod.GET, null,
//                new ParameterizedTypeReference<Iterable<PrivacyChoice>>() { }).getBody());
//    }

    public Iterable<PrivacyChoiceResponse> getPrivacyPolicyChoices() {
        return () -> StreamSupport.stream(template.exchange(cloudAddress + "/choice", HttpMethod.GET, null,
                new ParameterizedTypeReference<Iterable<PrivacyChoice>>() {
                }).getBody().spliterator(), false)
                .map(choice -> privacyChoiceIndexRepository.findById(choice.getId())
                        .map(choiceIndex -> PrivacyChoiceResponse.builder()
                                .id(choiceIndex.getId())
                                .localDateTime(choiceIndex.getLocalDateTime())
                                .privacyContent(choice.getPrivacyContent())
                                .build()).get())
                .iterator();
    }
}
