// Copyright (c) 2020 UWB & LESP.
// The UWB & LESP license this file to you under the MIT license.

package cz.senslog.connector.model.converter;

import cz.senslog.connector.model.api.Converter;
import cz.senslog.connector.model.azure.AzureModel;
import cz.senslog.connector.model.azure.SensorData;
import cz.senslog.connector.model.azure.SensorInfo;
import cz.senslog.connector.model.v2.Observation;
import cz.senslog.connector.model.v2.SenslogV2Model;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * The class {@code AzureModelSenslogV2ModelConverter} represents an implementation of converter
 * between {@link AzureModel} and {@link SenslogV2Model}.
 *
 * Converter converts input model of sensors data to observations. Each physical quantity of sensor
 * is converted as a single observation.
 *
 * @author Lukas Cerny
 * @version 1.0
 * @since 1.0
 */
public class AzureModelSenslogV2ModelConverter implements Converter<AzureModel, SenslogV2Model> {

    private static final Logger logger = LogManager.getLogger(AzureModelSenslogV2ModelConverter.class);


    @Override
    public SenslogV2Model convert(AzureModel inputModel) {

        if (inputModel == null || inputModel.getSensors() == null) {
            logger.warn("Nothing to convert. Received model is empty.");
            return null;
        }

        List<SensorInfo> sensorInfos = inputModel.getSensors();

        logger.debug("Creating an empty list of observation.");
        List<Observation> observations = new ArrayList<>();

        for (SensorInfo sensorInfo : sensorInfos) {
            logger.debug("Converting sensor with Eui {}.", sensorInfo.getEui());

            // TODO EUI will be converted the same way like for the version 1 or will be used more efficient way to transfer the data
            Long unitId = 1L;
            if (unitId == null) {
                logger.error("EUI converter for '{}' does not exist.", sensorInfo.getEui());
                continue;
            }

            for (SensorData sensorData : sensorInfo.getData()) {
                for (Map.Entry<String, Float> sensorDataEntry : sensorData.getValues().entrySet()) {
                    logger.debug("Creating a new observation.");
                    Observation observation = new Observation();
                    observation.setTimestamp(sensorData.getTime().toLocalDateTime());
                    observation.setValue(sensorDataEntry.getValue().doubleValue());

                    // TODO
                    observation.setId(unitId);
                    // observation.setSensorId(sensorDataEntry.getKey().getId());

                    logger.debug("Saving the new observation.");
                    observations.add(observation);
                }
            }
        }

        logger.debug("Creating a new SenslogV2 model.");
        SenslogV2Model outputModel = new SenslogV2Model(observations, inputModel.getFrom(), inputModel.getTo());;
        logger.debug("Conversion was completed successfully.");
        return outputModel;
    }
}
