package cz.senslog.connector.fetch.fieldclimate;

import cz.senslog.connector.model.config.DefaultConfig;
import cz.senslog.connector.fetch.fieldclimate.auth.AuthenticationService;
import cz.senslog.connector.tools.http.HttpClient;
import cz.senslog.connector.tools.http.HttpRequest;
import cz.senslog.connector.tools.http.HttpResponse;
import cz.senslog.connector.model.fieldclimate.*;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.mockito.stubbing.Answer;

import java.time.LocalDateTime;
import java.util.*;

import static cz.senslog.connector.tools.http.HttpCode.OK;
import static cz.senslog.connector.tools.http.HttpCode.SERVER_ERROR;
import static java.lang.String.format;
import static java.time.format.DateTimeFormatter.ofPattern;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

class FieldClimateFetcherTest {

    private static FieldClimateConfig config;
    private static AuthenticationService authService;
    private static LocalDateTime startDate = LocalDateTime.of(2019, 3, 6, 00, 00,0);

    @BeforeAll
    static void init() {
        DefaultConfig fcDConfig = new DefaultConfig("fcConfig", null);
        fcDConfig.setProperty("stationsHost", new HashMap<String, String>(){{
            put("domain", "https://api.fieldclimate.com/v1");
            put("path", "/user/stations");
        }});

        fcDConfig.setProperty("stationDataHost", new HashMap<String, String>(){{
            put("domain", "https://api.fieldclimate.com/v1");
            put("path", "/data/normal/{station_id}/raw/from/{from}/to/{to}");
        }});

        fcDConfig.setProperty("stationTimeRangeHost", new HashMap<String, String>(){{
            put("domain", "https://api.fieldclimate.com/v1");
            put("path", "/data/{station_id}");
        }});

        fcDConfig.setProperty("authentication", new HashMap<String, String>(){{
            put("publicKey", "3737ed4fe98fae975e54991216ed473c8d7db48662deff19");
            put("privateKey", "ed2e4abacdaad1d542eeabcec4ee4f6c8fbf3b8bb167b84b");
        }});


        fcDConfig.setProperty("sessionProxy", new HashMap<String, Object>(){{
            put("user", "<username>");
            put("group", "<group>");
            put("lastObservationHost",  new HashMap<String, String>(){{
                put("domain", "http://127.0.0.1:9080");
                put("path", "SensorService");
            }});
        }});

        Map<String, List<Integer>> allowedStation = new HashMap<>();
        List<Integer> allowedSensor = new ArrayList<>();
        allowedSensor.add((int)SensorType.HC_AIR_TEMPERATURE.getCode());
        allowedStation.put("original_name", allowedSensor);

        fcDConfig.setProperty("allowedStation", allowedStation);
        fcDConfig.setProperty("timeZone", "Europe/Riga");

        fcDConfig.setProperty("startDate", startDate);
        fcDConfig.setProperty("period", 12);

        config = new FieldClimateConfig(fcDConfig);
        authService = new AuthenticationService(config.getAuthentication());
    }

    @Test
    void init_GetStations() throws Exception {

        HttpClient httpClient = mock(HttpClient.class);
        when(httpClient.send(any(HttpRequest.class))).thenAnswer((Answer<HttpResponse>) invocationOnMock -> {
            HttpRequest request = invocationOnMock.getArgument(0, HttpRequest.class);
            String path = request.getUrl().getPath();
            if (path.contains("/user/stations")) {
                StationInfo stationInfo = new StationInfo();
                StationInfo.Name stationName = new StationInfo.Name();
                stationName.setOriginal("original_name");
                stationInfo.setName(stationName);
                String stationsJson = singletonList(stationInfo).toString();
                return HttpResponse.newBuilder()
                        .status(OK).body(stationsJson).build();
            }
            return HttpResponse.newBuilder()
                    .status(SERVER_ERROR).build();
        });
        FieldClimateFetcher fetcher = new FieldClimateFetcher(config, authService, httpClient);

        fetcher.init();
    }

    @Test
    void init_StationsRequestError_Exception() {

        HttpClient httpClient = mock(HttpClient.class);
        when(httpClient.send(any(HttpRequest.class))).thenAnswer((Answer<HttpResponse>) invocationOnMock ->
            HttpResponse.newBuilder().status(SERVER_ERROR).build()
        );
        FieldClimateFetcher fetcher = new FieldClimateFetcher(config, authService, httpClient);

        Assertions.assertThrows(Exception.class, fetcher::init);
    }

    @Test
    void init_NoneStations_Exception() {

        HttpClient httpClient = mock(HttpClient.class);
        when(httpClient.send(any(HttpRequest.class))).thenAnswer((Answer<HttpResponse>) invocationOnMock -> {
            HttpRequest request = invocationOnMock.getArgument(0, HttpRequest.class);
            String path = request.getUrl().getPath();
            if (path.contains("/user/stations")) {
                return HttpResponse.newBuilder()
                        .status(OK).body(emptyList().toString()).build();
            }

            return HttpResponse.newBuilder().status(SERVER_ERROR).build();
        });
        FieldClimateFetcher fetcher = new FieldClimateFetcher(config, authService, httpClient);

        Assertions.assertThrows(Exception.class, fetcher::init);
    }

    @Test
    void fetch_EmptyStationName_EmptyModel() throws Exception {
        HttpClient httpClient = mock(HttpClient.class);
        when(httpClient.send(any(HttpRequest.class))).thenAnswer((Answer<HttpResponse>) invocationOnMock -> {
            HttpRequest request = invocationOnMock.getArgument(0, HttpRequest.class);
            String path = request.getUrl().getPath();
            if (path.contains("/user/stations")) {
                StationInfo stationInfo = new StationInfo();
                StationInfo.Name name = new StationInfo.Name();
                name.setOriginal("");
                stationInfo.setName(name);
                List<StationInfo> stations = singletonList(stationInfo);
                return HttpResponse.newBuilder()
                        .status(OK).body(stations.toString()).build();
            }
            return HttpResponse.newBuilder()
                    .status(SERVER_ERROR).build();
        });
        FieldClimateFetcher fetcher = new FieldClimateFetcher(config, authService, httpClient);
        fetcher.init();

        FieldClimateModel model = fetcher.fetch(Optional.empty());

        assertTrue(model.getStations().isEmpty());
    }

    @Test
    void fetch_StationTimeRangeRequestError_EmptyModel() throws Exception {
        String stationName = "original_name";
        HttpClient httpClient = mock(HttpClient.class);
        when(httpClient.send(any(HttpRequest.class))).thenAnswer((Answer<HttpResponse>) invocationOnMock -> {
            HttpRequest request = invocationOnMock.getArgument(0, HttpRequest.class);
            String path = request.getUrl().getPath();
            if (path.contains("/user/stations")) {
                StationInfo stationInfo = new StationInfo();
                StationInfo.Name name = new StationInfo.Name();
                name.setOriginal(stationName);
                stationInfo.setName(name);
                List<StationInfo> stations = singletonList(stationInfo);
                return HttpResponse.newBuilder()
                        .status(OK).body(stations.toString()).build();
            }
            if (path.contains("/data/"+stationName)) {
                return HttpResponse.newBuilder()
                        .status(SERVER_ERROR).build();
            }
            return HttpResponse.newBuilder()
                    .status(SERVER_ERROR).build();
        });
        FieldClimateFetcher fetcher = new FieldClimateFetcher(config, authService, httpClient);
        fetcher.init();

        FieldClimateModel model = fetcher.fetch(Optional.empty());

        assertTrue(model.getStations().isEmpty());
    }

    @Test
    void fetch_StationTimeRangeBadData_EmptyModel() throws Exception {
        String stationName = "original_name";
        HttpClient httpClient = mock(HttpClient.class);
        when(httpClient.send(any(HttpRequest.class))).thenAnswer((Answer<HttpResponse>) invocationOnMock -> {
            HttpRequest request = invocationOnMock.getArgument(0, HttpRequest.class);
            String path = request.getUrl().getPath();
            if (path.contains("/user/stations")) {
                StationInfo stationInfo = new StationInfo();
                StationInfo.Name name = new StationInfo.Name();
                name.setOriginal(stationName);
                stationInfo.setName(name);
                StationInfo.Dates dates = new StationInfo.Dates();
                dates.setMin_date(startDate);
                stationInfo.setDates(dates);
                List<StationInfo> stations = singletonList(stationInfo);
                return HttpResponse.newBuilder()
                        .status(OK).body(stations.toString()).build();
            }
            if (path.contains("/data/"+stationName)) {
                String json = String.format("{\"min_date\":\"%s\",\"max_date\":\"%s\"}", "unknown", "unknown");
                return HttpResponse.newBuilder().status(OK).body(json).build();
            }
            return HttpResponse.newBuilder()
                    .status(SERVER_ERROR).build();
        });
        FieldClimateFetcher fetcher = new FieldClimateFetcher(config, authService, httpClient);
        fetcher.init();

        FieldClimateModel model = fetcher.fetch(Optional.empty());

        assertTrue(model.getStations().isEmpty());
    }

    @Test
    void fetch_StationDataErrorRequest_EmptyModel() throws Exception {
        String stationName = "original_name";
        HttpClient httpClient = mock(HttpClient.class);
        when(httpClient.send(any(HttpRequest.class))).thenAnswer((Answer<HttpResponse>) invocationOnMock -> {
            HttpRequest request = invocationOnMock.getArgument(0, HttpRequest.class);
            String path = request.getUrl().getPath();
            if (path.contains("/user/stations")) {
                StationInfo stationInfo = new StationInfo();
                StationInfo.Name name = new StationInfo.Name();
                name.setOriginal(stationName);
                stationInfo.setName(name);
                List<StationInfo> stations = singletonList(stationInfo);
                return HttpResponse.newBuilder()
                        .status(OK).body(stations.toString()).build();
            }
            if (path.contains("/data/"+stationName)) {
                String json = String.format("{\"min_date\":\"%s\",\"max_date\":\"%s\"}",
                        startDate.minusDays(1).format(ofPattern("yyyy-MM-dd HH:mm:ss")),
                        startDate.plusDays(1).format(ofPattern("yyyy-MM-dd HH:mm:ss"))
                );
                return HttpResponse.newBuilder().status(OK).body(json).build();
            }
            if (path.contains("/data/normal/"+stationName)) {
                return HttpResponse.newBuilder()
                        .status(SERVER_ERROR).build();
            }
            return HttpResponse.newBuilder()
                    .status(SERVER_ERROR).build();
        });
        FieldClimateFetcher fetcher = new FieldClimateFetcher(config, authService, httpClient);
        fetcher.init();

        FieldClimateModel model = fetcher.fetch(Optional.empty());

        assertTrue(model.getStations().isEmpty());
    }

    @Test
    void fetch_StationDataBadJson_EmptyModel() throws Exception {
        String stationName = "original_name";
        HttpClient httpClient = mock(HttpClient.class);
        when(httpClient.send(any(HttpRequest.class))).thenAnswer((Answer<HttpResponse>) invocationOnMock -> {
            HttpRequest request = invocationOnMock.getArgument(0, HttpRequest.class);
            String path = request.getUrl().getPath();
            if (path.contains("/user/stations")) {
                StationInfo stationInfo = new StationInfo();
                StationInfo.Name name = new StationInfo.Name();
                name.setOriginal(stationName);
                stationInfo.setName(name);
                List<StationInfo> stations = singletonList(stationInfo);
                return HttpResponse.newBuilder()
                        .status(OK).body(stations.toString()).build();
            }
            if (path.contains("/data/"+stationName)) {
                String json = String.format("{\"min_date\":\"%s\",\"max_date\":\"%s\"}",
                        startDate.minusDays(1).format(ofPattern("yyyy-MM-dd HH:mm:ss")),
                        startDate.plusDays(1).format(ofPattern("yyyy-MM-dd HH:mm:ss"))
                );
                return HttpResponse.newBuilder().status(OK).body(json).build();
            }
            if (path.contains("/data/normal/"+stationName)) {
                return HttpResponse.newBuilder()
                        .status(OK).body("unknown").build();
            }
            return HttpResponse.newBuilder()
                    .status(SERVER_ERROR).build();
        });
        FieldClimateFetcher fetcher = new FieldClimateFetcher(config, authService, httpClient);
        fetcher.init();

        FieldClimateModel model = fetcher.fetch(Optional.empty());

        assertTrue(model.getStations().isEmpty());
    }

    @Test
    void fetch_Valid_Model() throws Exception {
        String stationName = "original_name";
        HttpClient httpClient = mock(HttpClient.class);
        when(httpClient.send(any(HttpRequest.class))).thenAnswer((Answer<HttpResponse>) invocationOnMock -> {
            HttpRequest request = invocationOnMock.getArgument(0, HttpRequest.class);
            String path = request.getUrl().getPath();
            if (path.contains("/user/stations")) {
                StationInfo stationInfo = new StationInfo();
                StationInfo.Name name = new StationInfo.Name();
                name.setOriginal(stationName);
                stationInfo.setName(name);
                List<StationInfo> stations = singletonList(stationInfo);
                return HttpResponse.newBuilder()
                        .status(OK).body(stations.toString()).build();
            }
            if (path.contains("/data/"+stationName)) {
                String json = String.format("{\"min_date\":\"%s\",\"max_date\":\"%s\"}",
                        startDate.plusHours(1).format(ofPattern("yyyy-MM-dd HH:mm:ss")),
                        startDate.plusHours(2).format(ofPattern("yyyy-MM-dd HH:mm:ss"))
                );
                return HttpResponse.newBuilder().status(OK).body(json).build();
            }
            if (path.contains("/data/normal/"+stationName)) {
                StationData data = new StationData();
                data.setId(stationName);
                SensorDataInfo dataInfo = new SensorDataInfo();
                dataInfo.setName("sensorName");
                dataInfo.setCh(1L);
                dataInfo.setCode(SensorType.HC_AIR_TEMPERATURE.getCode());
                dataInfo.setMac("mac");
                dataInfo.setSerial("serial");
                Map<String, Integer> aggrMap = new HashMap<>();
                aggrMap.put("avg", 1);
                dataInfo.setAggr(aggrMap);
                Map<String, String> dataMap = new HashMap<>();
                String sensorDataHash = format("%s_%s_%s_%s_%s",
                        dataInfo.getCh(), dataInfo.getMac(), dataInfo.getSerial(), dataInfo.getCode(), "avg");
                dataMap.put(sensorDataHash, "100");
                dataMap.put("date", startDate.plusHours(1).plusMinutes(5).format(ofPattern("yyyy-MM-dd HH:mm:ss")));
                data.setSensors(singletonList(dataInfo));
                data.setData(singletonList(dataMap));
                String json = data.toString();
                return HttpResponse.newBuilder()
                        .status(OK).body(json).build();
            }
            return HttpResponse.newBuilder()
                    .status(SERVER_ERROR).build();
        });
        FieldClimateFetcher fetcher = new FieldClimateFetcher(config, authService, httpClient);
        fetcher.init();

        FieldClimateModel model = fetcher.fetch(Optional.empty());

        assertEquals(1, model.getStations().size());

        StationData stationData = model.getStations().get(0);
        assertEquals(stationName, stationData.getId());

        assertEquals(1, stationData.getSensors().size());
        assertEquals(1, stationData.getData().size());

        SensorDataInfo dataInfo = stationData.getSensors().get(0);
        Map<String, String> data = stationData.getData().get(0);
        assertEquals("sensorName", dataInfo.getName());
        String sensorDataHash = format("%s_%s_%s_%s_%s",
                dataInfo.getCh(), dataInfo.getMac(), dataInfo.getSerial(), dataInfo.getCode(),
                dataInfo.getAggr().entrySet().iterator().next().getKey());
        assertEquals(100, Integer.valueOf(data.get(sensorDataHash)));
    }

    @Test
    void fetch_TimeRange_EmptyModel() throws Exception {
        String stationName = "original_name";
        HttpClient httpClient = mock(HttpClient.class);
        when(httpClient.send(any(HttpRequest.class))).thenAnswer((Answer<HttpResponse>) invocationOnMock -> {
            HttpRequest request = invocationOnMock.getArgument(0, HttpRequest.class);
            String path = request.getUrl().getPath();
            if (path.contains("/user/stations")) {
                StationInfo stationInfo = new StationInfo();
                StationInfo.Name name = new StationInfo.Name();
                name.setOriginal(stationName);
                stationInfo.setName(name);
                List<StationInfo> stations = singletonList(stationInfo);
                return HttpResponse.newBuilder()
                        .status(OK).body(stations.toString()).build();
            }
            if (path.contains("/data/"+stationName)) {
                String json = String.format("{\"min_date\":\"%s\",\"max_date\":\"%s\"}",
                        startDate.minusDays(1).format(ofPattern("yyyy-MM-dd HH:mm:ss")),
                        startDate.plusDays(1).format(ofPattern("yyyy-MM-dd HH:mm:ss"))
                );
                return HttpResponse.newBuilder().status(OK).body(json).build();
            }
            if (path.contains("/data/normal/"+stationName)) {
                StationData data = new StationData();
                data.setId(stationName);
                SensorDataInfo dataInfo = new SensorDataInfo();
                dataInfo.setName("sensorName");
                dataInfo.setCh(1L);
                dataInfo.setCode(SensorType.HC_AIR_TEMPERATURE.getCode());
                Map<String, Integer> aggrMap = new HashMap<>();
                aggrMap.put("avg", 1);
                dataInfo.setAggr(aggrMap);
                Map<String, String> dataMap = new HashMap<>();
                dataMap.put("date", startDate.plusHours(1).format(ofPattern("yyyy-MM-dd HH:mm:ss")));
                data.setSensors(singletonList(dataInfo));
                data.setData(singletonList(dataMap));
                String json = data.toString();
                return HttpResponse.newBuilder()
                        .status(OK).body(json).build();
            }
            return HttpResponse.newBuilder()
                    .status(SERVER_ERROR).build();
        });
        FieldClimateFetcher fetcher = new FieldClimateFetcher(config, authService, httpClient);
        fetcher.init();

        FieldClimateModel model1 = fetcher.fetch(Optional.empty());
    }

    /*
    @Test
    void proxyFetch() throws Exception {

        DefaultConfig propertyConfig = new DefaultConfig("proxySession", null);
        propertyConfig.setProperty("lastObservationHost", new HashMap<String, String>() {{
            put("domain", "http://51.15.45.95:8080/senslog1");
            put("path", "SensorService");
        }});
        propertyConfig.setProperty("user", "vilcini");
        propertyConfig.setProperty("group", "vilcini");

        FieldClimateSessionProxyConfig sessionProxyConfig = new FieldClimateSessionProxyConfig(propertyConfig);

        FieldClimateFetcher fetcher = new FieldClimateFetcher(config, authService, newHttpSSLClient());
        FieldClimateProxySession proxySession = new FieldClimateProxySession(fetcher, sessionProxyConfig, newHttpClient());

        ExecutableFetcher<FieldClimateModel> executableFetcher = ExecutableFetcher.createWithProxySession(proxySession);
        executableFetcher.getRawFetcher().init();

        executableFetcher.execute();
        executableFetcher.execute();
    }

     */
/*
    @Test
    void fetch() throws Exception {

        DefaultConfig fcDConfig = new DefaultConfig("fcConfig", null);
        fcDConfig.setProperty("stationsHost", new HashMap<String, String>(){{
            put("domain", "https://api.fieldclimate.com/v1");
            put("path", "/user/stations");
        }});

        fcDConfig.setProperty("stationDataHost", new HashMap<String, String>(){{
            put("domain", "https://api.fieldclimate.com/v1");
            put("path", "/data/normal/{station_id}/raw/from/{from}/to/{to}");
        }});

        fcDConfig.setProperty("stationTimeRangeHost", new HashMap<String, String>(){{
            put("domain", "https://api.fieldclimate.com/v1");
            put("path", "/data/{station_id}");
        }});

        fcDConfig.setProperty("authentication", new HashMap<String, String>(){{
            put("publicKey", "3737ed4fe98fae975e54991216ed473c8d7db48662deff19");
            put("privateKey", "ed2e4abacdaad1d542eeabcec4ee4f6c8fbf3b8bb167b84b");
        }});

        fcDConfig.setProperty("timeZone", "Europe/Riga");

        fcDConfig.setProperty("blockedStations", new ArrayList<String>(){{
             add("0120821D");
             add("0120821E");
            // add("00208048");
        }});

        Map<String, Object> sessionProxy = new HashMap<>();
        sessionProxy.put("lastObservationHost", new HashMap<String, String>() {{
            put("domain", "http://51.15.45.95:8080/senslog1");
            put("path", "SensorService");
        }});
        sessionProxy.put("user", "vilcini");
        sessionProxy.put("group", "vilcini");
        fcDConfig.setProperty("sessionProxy", sessionProxy);

        fcDConfig.setProperty("startDate", LocalDateTime.of(2020, 7, 1, 7, 45,0));
        fcDConfig.setProperty("period", 1);

        FieldClimateConfig config = new FieldClimateConfig(fcDConfig);
        FieldClimateFetcher fetcher = new FieldClimateFetcher(config, authService, HttpClient.newHttpSSLClient());
        FieldClimateProxySession proxySession = new FieldClimateProxySession(fetcher, config.getSessionProxy(), newHttpClient());

//        ExecutableFetcher<FieldClimateModel> executableFetcher = ExecutableFetcher.createWithProxySession(proxySession);
        ExecutableFetcher<FieldClimateModel> executableFetcher = ExecutableFetcher.create(fetcher);

        executableFetcher.getRawFetcher().init();


        for (int i = 0; i < 10; i++) {
            FieldClimateModel fieldClimateModel = executableFetcher.execute();
            final FieldClimateModelSenslogV1ModelConverter converter = new FieldClimateModelSenslogV1ModelConverter();
            SenslogV1Model senslogV1Model = converter.convert(fieldClimateModel);
            System.out.println(senslogV1Model);
        }
    }
*/

    /*
    private void saveToCSV(FieldClimateModel model) throws IOException {

        String [] header = new String[] {
                "name", "ch", "code", "serial", "mac", "timestamp"
        };

        String [] valueType = new String[] {
                "avg", "min", "last", "max", "sum", "time"
        };
        
        String delimiter = ";";

        for (StationData station : model.getStations()) {

            StringBuilder stationSheet = new StringBuilder();

            // header
            stationSheet.append(String.join(delimiter, header));
            stationSheet.append(delimiter);
            stationSheet.append(String.join(delimiter, valueType));
            stationSheet.append("\n");

            for (Map<String, String> stationData : station.getData()) {
                String timestamp = stationData.getOrDefault("date", "");

                Set<String> done = new HashSet<>();
                for (Map.Entry<String, String> dataEntry : stationData.entrySet()) {
                    String key = dataEntry.getKey();
                    String value = dataEntry.getValue();

                    if (key.contains("_")) {
                        String [] cmp = key.split("_");

                        String ch = cmp[0];
                        String mac = cmp[1];
                        String serial = cmp[2];
                        String code = cmp[3];
                        String aggr = cmp[4];

                        SensorDataInfo sensor = findSensor(station.getSensors(), Integer.valueOf(ch), mac, serial, Integer.valueOf(code));

                        String sensorHash = format("%s_%s_%s_%s", sensor.getCh(), sensor.getMac(), sensor.getSerial(), sensor.getCode());

                        if (done.contains(sensorHash)) continue;

                        StringBuilder sensorBuilder = new StringBuilder();
                        sensorBuilder.append(sensor.getName()).append(delimiter);
                        sensorBuilder.append(sensor.getCh()).append(delimiter);
                        sensorBuilder.append(sensor.getCode()).append(delimiter);
                        sensorBuilder.append(sensor.getSerial()).append(delimiter);
                        sensorBuilder.append(sensor.getMac());
                        String sensorLine = sensorBuilder.toString();

                        StringBuilder valueBuilder = new StringBuilder();
                        for (String type : valueType) {

                            String sensorDataHash = format("%s_%s", sensorHash, type);

                            if (stationData.containsKey(sensorDataHash)) {
                                valueBuilder.append(stationData.get(sensorDataHash));
                            }
                            valueBuilder.append(delimiter);
                        }
                        String valuesLine = valueBuilder.toString();


                        stationSheet.append(sensorLine).append(delimiter)
                                .append(timestamp).append(delimiter)
                                .append(valuesLine).append("\n");

                        done.add(sensorHash);
                    }
                }
            }

            Path filePath = Paths.get("sensor_" + station.getStationId()+ ".csv");
            Files.write(filePath, Collections.singleton(stationSheet.toString()));
        }
    }

    private SensorDataInfo findSensor(List<SensorDataInfo> sensors, Integer ch, String mac, String serial, Integer code) {
        for (SensorDataInfo sensor : sensors) {
            if (sensor.getCode().equals(code) &&
                    sensor.getCh().equals(ch) &&
                    sensor.getMac().equals(mac) &&
                    sensor.getSerial().equals(serial)
            ) {
                return sensor;
            }
        }

        return null;
    }
    */
}