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

import edu.prlab.tyler.iotgateway.cloud.pojo.device.Device;
import edu.prlab.tyler.iotgateway.cloud.pojo.privacy.PrivacyChoice;
import edu.prlab.tyler.iotgateway.cloud.pojo.privacy.PrivacyPolicyReport;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.Optional;
import java.util.function.Supplier;

@Service
public class RemoteService {
    private RestTemplate template;
    private String cloudAddress;

    @Autowired
    public RemoteService(RestTemplate template) {
        this.template = template;
    }

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

    public Optional<Device> readDevice(String udn) {
        return tryCatch(() -> template.exchange(cloudAddress + "/device/" + udn, HttpMethod.GET, null,
                Device.class).getBody(), "Read device error");
    }

    public Optional<Iterable<Device>> readDevices() {
        return tryCatch(() -> template.exchange(cloudAddress + "/device", HttpMethod.GET, null,
                new ParameterizedTypeReference<Iterable<Device>>() {
                }).getBody(), "Read devices error");
    }

    public Optional<PrivacyPolicyReport> readRelatedPrivacyPolicies(String udn) {
        return tryCatch(() -> template.exchange(cloudAddress + "/privacy/" + udn, HttpMethod.GET, null,
                PrivacyPolicyReport.class).getBody(), "Read privacyPolicyReport error");
    }

    public Optional<PrivacyChoice> setPrivacyChoice(PrivacyChoice choice) {
        return tryCatch(() -> template.exchange(cloudAddress + "/choice", HttpMethod.POST,
                new HttpEntity(choice), PrivacyChoice.class).getBody(), "Set privacyChoice error");
    }

    public Optional<Iterable<PrivacyChoice>> readPrivacyChoices() {
        return tryCatch(() -> template.exchange(cloudAddress + "/choice", HttpMethod.GET, null,
                new ParameterizedTypeReference<Iterable<PrivacyChoice>>() {
                }).getBody(), "Read privacyChoice error");
    }

    public <T> Optional<T> tryCatch(Supplier<T> supplier, String errorMessage) {
        try {
            return Optional.of(supplier.get());
        } catch (Exception e) {
            System.out.println(errorMessage);
            e.printStackTrace();
            return Optional.empty();
        }
    }
}
