package ru.kirillius.cooler.controller.CLI;

import ru.kirillius.cooler.controller.API.DataType;
import ru.kirillius.cooler.controller.API.MessageSystem;
import ru.kirillius.cooler.controller.API.Operation;
import ru.kirillius.cooler.controller.ExtMath;

public class ReactiveMenuItemBinding implements MenuItem<Void> {
    protected MessageSystem messageSystem;
    protected DataType dataType;
    protected String title;
    protected String units;
    protected float minValue;
    protected float maxValue;
    protected float multiplier;
    private Integer valueCache = null;

    public ReactiveMenuItemBinding(MessageSystem messageSystem, DataType dataType, String title, String units, float minValue, float maxValue, float multiplier) {
        this.messageSystem = messageSystem;
        this.dataType = dataType;
        this.title = title;
        this.units = units;
        this.minValue = minValue;
        this.maxValue = maxValue;
        this.multiplier = multiplier;
    }

    @Override
    public String render() {
        StringBuilder builder = new StringBuilder();
        Operation operation;
        int value;
        if (valueCache == null) {
            operation = messageSystem.getValue(dataType);
            operation.waitForReturn();
            if (!operation.isSuccessful()) return "Failed to read " + dataType;
            value = Byte.toUnsignedInt(operation.getValue());
            valueCache = value;
        } else {
            value = valueCache;
        }

        var t = ExtMath.clamp(ExtMath.inverseLerp(minValue, maxValue, value), 100, 0) * 10;
        builder.append(title).append(" [");
        for (int i = 0; i < t; i++) builder.append("+");
        for (int i = (int) t; i < 10; i++) builder.append("-");
        builder.append("] ").append(value / multiplier).append(units);
        return builder.toString();
    }

    @Override
    public Void select() {
        float value;
        System.out.print("Set new value [" + (minValue / multiplier) + "-" + (maxValue / multiplier) + "]: ");
        try {
            value = Float.parseFloat(ConsoleApp.input.readLine());
        } catch (Exception e) {
            System.err.println("Invalid value!");
            return null;
        }

        Operation operation = messageSystem.setValue(dataType, (byte) ExtMath.clamp(value * multiplier, maxValue, minValue));
        operation.waitForReturn();
        if (!operation.isSuccessful()) {
            System.err.println("Failed to set value!");
            valueCache = null;
        } else {
            valueCache = Byte.toUnsignedInt(operation.getValue());
        }
        return null;
    }
}
