package eu.teraflow.automation.context;

import context.ContextOuterClass;
import context.ContextService;
import eu.teraflow.automation.device.Device;
import eu.teraflow.automation.device.model.*;
import io.quarkus.grpc.GrpcClient;
import io.smallrye.mutiny.Uni;
import javax.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class ContextGatewayImpl implements ContextGateway {

    @GrpcClient ContextService delegate;

    @Override
    public Uni<Device> getDevice(DeviceId deviceId) {
        final var serializedDeviceId = getSerializedDeviceId(deviceId);
        final var serializedDeviceUni = delegate.getDevice(serializedDeviceId);

        return serializedDeviceUni.onItem().transform(this::getDevice);
    }

    private Device getDevice(ContextOuterClass.Device device) {

        final var deviceId = getDeviceId(device.getDeviceId());
        final var deviceType = getDeviceType(device.getDeviceType());
        final var deviceOperationalStatus =
                getDeviceOperationalStatus(device.getDeviceOperationalStatus());

        return new Device(deviceId, deviceType, deviceOperationalStatus);
    }

    private DeviceId getDeviceId(ContextOuterClass.DeviceId deviceId) {
        Uuid uuid = new Uuid(deviceId.getDeviceUuid().getUuid());
        return new DeviceId(uuid);
    }

    private DeviceType getDeviceType(String deviceType) {
        return new DeviceType(deviceType);
    }

    private DeviceOperationalStatus getDeviceOperationalStatus(
            ContextOuterClass.DeviceOperationalStatusEnum deviceOperationalStatusEnum) {

        if (deviceOperationalStatusEnum
                == ContextOuterClass.DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_ENABLED) {
            return DeviceOperationalStatus.ENABLED;
        } else if (deviceOperationalStatusEnum
                == ContextOuterClass.DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_DISABLED) {
            return DeviceOperationalStatus.DISABLED;
        } else {
            return DeviceOperationalStatus.UNDEFINED;
        }
    }

    private ContextOuterClass.DeviceId getSerializedDeviceId(DeviceId deviceId) {
        final var deviceIdUuid =
                ContextOuterClass.Uuid.newBuilder().setUuid(deviceId.toString()).build();
        return ContextOuterClass.DeviceId.newBuilder().setDeviceUuid(deviceIdUuid).build();
    }
}
