/*
 * Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package eu.teraflow.automation;

import automation.Automation;
import context.ContextOuterClass;
import eu.teraflow.automation.device.model.Device;
import eu.teraflow.automation.model.DeviceRoleId;
import io.quarkus.grpc.GrpcService;
import io.smallrye.mutiny.Uni;
import javax.inject.Inject;

@GrpcService
public class AutomationGatewayImpl implements AutomationGateway {

    private final AutomationService automationService;
    private final Serializer serializer;

    @Inject
    public AutomationGatewayImpl(AutomationService automationService, Serializer serializer) {
        this.automationService = automationService;
        this.serializer = serializer;
    }

    @Override
    public Uni<Automation.DeviceRole> ztpGetDeviceRole(Automation.DeviceRoleId request) {
        return Uni.createFrom()
                .item(() -> Automation.DeviceRole.newBuilder().setDevRoleId(request).build());
    }

    @Override
    public Uni<Automation.DeviceRoleList> ztpGetDeviceRolesByDeviceId(
            ContextOuterClass.DeviceId request) {
        return Uni.createFrom().item(() -> Automation.DeviceRoleList.newBuilder().build());
    }

    @Override
    public Uni<Automation.DeviceRoleState> ztpAdd(Automation.DeviceRole request) {
        final var devRoleId = request.getDevRoleId().getDevRoleId().getUuid();
        final var deviceId = serializer.deserialize(request.getDevRoleId().getDevId());

        return automationService
                .addDevice(deviceId)
                .onItem()
                .transform( device -> transformToDeviceRoleState(device, devRoleId));
    }

    @Override
    public Uni<Automation.DeviceRoleState> ztpUpdate(Automation.DeviceRole request) {
        return Uni.createFrom()
                .item(
                        () ->
                                Automation.DeviceRoleState.newBuilder()
                                        .setDevRoleId(request.getDevRoleId())
                                        .build());
    }

    @Override
    public Uni<Automation.DeviceRoleState> ztpDelete(Automation.DeviceRole request) {
        return Uni.createFrom()
                .item(
                        () ->
                                Automation.DeviceRoleState.newBuilder()
                                        .setDevRoleId(request.getDevRoleId())
                                        .build());
    }

    @Override
    public Uni<Automation.DeviceDeletionResult> ztpDeleteAll(Automation.Empty empty) {
        return Uni.createFrom().item(() -> Automation.DeviceDeletionResult.newBuilder().build());
    }

    // TODO When `DeviceRoleState` domain object will be created, move this method to Serializer class and create related tests
    private Automation.DeviceRoleState transformToDeviceRoleState(Device device, String devRoleId){

        final var deviceRoleId = new DeviceRoleId(devRoleId, device.getDeviceId());
        final var serializeDeviceRoleId = serializer.serialize(deviceRoleId);

        return Automation.DeviceRoleState.newBuilder()
                .setDevRoleId(serializeDeviceRoleId)
                .setDevRoleState(Automation.ZtpDeviceState.ZTP_DEV_STATE_CREATED)
                .build();
    }
}