package cz.senslog.connector.model.fieldclimate;

import java.util.*;

/**
 * The enum {@code SensorType} represents type of sensor
 * which each physical quantity is represents by identifier.
 *
 * @author Lukas Cerny
 * @version 1.0
 * @since 1.0
 */
public enum SensorType {

    EAG_SOIL_MOISTURE       (19969, 410160000, Group.MULTICHANNEL), // [%]
    EAG_SOIL_SALINITY       (20228, 800010000, Group.MULTICHANNEL), // [VIC]
    SOIL_TEMPERATURE        (17153, 340410000, Group.MULTICHANNEL), // [°C]
    LEAF_WETNESS            (4, 790010000),     // [min]
    WIND_SPEED              (5, 470110000),     // [m/s]
    PRECIPITATION           (6, 480070000),     // [mm]
    WIND_DIRECTION          (143, 470130000),   // [deg]
    WIND_SPEED_MAX          (49, 470120000),    // [m/s]
    DEW_POINT               (21, 420050000),    // [°C]
    SOLAR_RADIATION         (600, 620020000),   // [W/m2]
    BATTERY                 (7, 360220000),     // [mV]
    SOLAR_PANEL             (30, 360230000),    // [mV]
    VPD                     (25, 460070000),    // [mBar]
    DELTA_T                 (27, 810010000),    // [°C]

    HC_AIR_TEMPERATURE      (506, 340400000),   // [°C]
    HC_RELATIVE_HUMIDITY    (507, 410170000),   // [%]
    HC_SERIAL_NUMBER        (508, 680030000),



    LATITUDE                (650, Group.POSITION),
    LONGITUDE               (651, Group.POSITION),
    ALTITUDE                (652, Group.POSITION),
    HDOP                    (659, Group.POSITION), // Horizontal dilution  of position
    
    ;

    public enum Group {
        POSITION, MULTICHANNEL
    }

    private static final Map<Long, SensorType> VALUES;
    static {
        VALUES = new HashMap<>();
        for (SensorType value : values()) {
            VALUES.put(value.code, value);
        }
    }

    private final long code, id;
    private final Group group;

    SensorType(long code, long id) {
        this(code, id, null);
    }

    SensorType(long code, Group group) {
        this(code, -1, group);
    }

    SensorType(long code, long id, Group group) {
        this.code = code;
        this.id = id;
        this.group = group;
    }

    public long getId() {
        return id;
    }

    public long getCode() {
        return code;
    }

    public boolean isGrouped() {
        return group != null;
    }

    public boolean isChanneled() {
        return group != null && group.equals(Group.MULTICHANNEL);
    }

    public Group getGroup() {
        return group;
    }

    public boolean containsGroup(Group group) {
        return group != null && this.group == group;
    }

    public static int countOfGroup(Group group) {
        int count = 0;
        for (SensorType value : values()) {
            if (value.getId() == -1 && value.group == group) {
                count++;
            }
        }
        return count;
    }

    public static Set<Long> getIDs() {
        Set<Long> ids = new HashSet<>(values().length);
        for (SensorType value : values()) {
            ids.add(value.code);
        }
        return ids;
    }

    public static SensorType of(long code) {
        return VALUES.getOrDefault(code, null);
    }
}
